Add vendor for github.com/containerd/imgcrypt
Updates to version using containerd v2.0.0-rc Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
parent
87bab6cdc7
commit
9857afda44
7
go.mod
7
go.mod
@ -19,6 +19,7 @@ require (
|
||||
github.com/containerd/fifo v1.1.0
|
||||
github.com/containerd/go-cni v1.1.9
|
||||
github.com/containerd/go-runc v1.1.0
|
||||
github.com/containerd/imgcrypt v1.1.12-0.20240528203804-3ca09a2db5cd
|
||||
github.com/containerd/log v0.1.0
|
||||
github.com/containerd/nri v0.6.1
|
||||
github.com/containerd/platforms v0.2.0
|
||||
@ -90,9 +91,11 @@ require (
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cilium/ebpf v0.11.0 // indirect
|
||||
github.com/containers/ocicrypt v1.1.10 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
@ -107,6 +110,7 @@ require (
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/mdlayher/socket v0.4.1 // indirect
|
||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
@ -117,12 +121,15 @@ require (
|
||||
github.com/prometheus/common v0.48.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.26.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.2.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/oauth2 v0.17.0 // indirect
|
||||
|
27
go.sum
27
go.sum
@ -53,6 +53,8 @@ github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9
|
||||
github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM=
|
||||
github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA=
|
||||
github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U=
|
||||
github.com/containerd/imgcrypt v1.1.12-0.20240528203804-3ca09a2db5cd h1:GjAKQysk1gNYupyhuvCyNvNRNtmPF7e8/+OhqT/8zu4=
|
||||
github.com/containerd/imgcrypt v1.1.12-0.20240528203804-3ca09a2db5cd/go.mod h1:HwgRdLSki2P6QOWbrqnK9vBs5Ew9WNjY1nPTB/xA9w0=
|
||||
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/nri v0.6.1 h1:xSQ6elnQ4Ynidm9u49ARK9wRKHs80HCUI+bkXOxV4mA=
|
||||
@ -69,6 +71,8 @@ github.com/containernetworking/cni v1.2.0 h1:fEjhlfWwWAXEvlcMQu/i6z8DA0Kbu7EcmR5
|
||||
github.com/containernetworking/cni v1.2.0/go.mod h1:/r+vA/7vrynNfbvSP9g8tIKEoy6win7sALJAw4ZiJks=
|
||||
github.com/containernetworking/plugins v1.4.1 h1:+sJRRv8PKhLkXIl6tH1D7RMi+CbbHutDGU+ErLBORWA=
|
||||
github.com/containernetworking/plugins v1.4.1/go.mod h1:n6FFGKcaY4o2o5msgu/UImtoC+fpQXM3076VHfHbj60=
|
||||
github.com/containers/ocicrypt v1.1.10 h1:r7UR6o8+lyhkEywetubUUgcKFjOWOaWz8cEBrCPX0ic=
|
||||
github.com/containers/ocicrypt v1.1.10/go.mod h1:YfzSSr06PTHQwSTUKqDSjish9BeW1E4HUmreluQcMd8=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
@ -96,6 +100,8 @@ github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx
|
||||
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
|
||||
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
@ -201,6 +207,8 @@ github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U
|
||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
|
||||
github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE=
|
||||
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
|
||||
@ -283,6 +291,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
@ -324,6 +334,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
|
||||
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0=
|
||||
@ -353,6 +365,9 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4=
|
||||
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
|
||||
@ -362,6 +377,7 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -377,6 +393,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -389,6 +407,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -410,16 +429,23 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
@ -433,6 +459,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
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.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
2
vendor/github.com/containerd/imgcrypt/.gitignore
generated
vendored
Normal file
2
vendor/github.com/containerd/imgcrypt/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*~
|
||||
/bin/
|
31
vendor/github.com/containerd/imgcrypt/.golangci.yml
generated
vendored
Normal file
31
vendor/github.com/containerd/imgcrypt/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
linters:
|
||||
enable:
|
||||
- depguard
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- gofmt
|
||||
- goimports
|
||||
- revive
|
||||
- ineffassign
|
||||
- vet
|
||||
- unused
|
||||
- misspell
|
||||
|
||||
run:
|
||||
skip-dirs:
|
||||
- cmd/ctr/commands/run
|
||||
- cmd/ctr/commands/images
|
||||
- cmd\\ctr\\commands\\run
|
||||
- cmd\\ctr\\commands\\images
|
||||
skip-files:
|
||||
- cmd/ctr/commands/commands.go
|
||||
- cmd\\ctr\\commands\\commands.go
|
||||
|
||||
linters-settings:
|
||||
depguard:
|
||||
rules:
|
||||
main:
|
||||
files:
|
||||
- $all
|
||||
deny:
|
||||
- pkg: "io/ioutil"
|
63
vendor/github.com/containerd/imgcrypt/CHANGES
generated
vendored
Normal file
63
vendor/github.com/containerd/imgcrypt/CHANGES
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
CHANGES
|
||||
|
||||
v1.1.10:
|
||||
- Updated to ocicrypt v1.1.10
|
||||
- Added test cases with JKW EC key and added 2 more RSA keys
|
||||
- Sync'ed enc-ctr with ctr of containerd v1.6.30
|
||||
- Updated dependencies
|
||||
|
||||
v1.1.9:
|
||||
- Updated to ocicrypt v1.1.9
|
||||
- Updated dependencies
|
||||
|
||||
v1.1.8:
|
||||
- Updated to containerd v1.6.23
|
||||
- Sync'ed enc-ctr with ctr of containerd v1.6.23
|
||||
- Updated to ocicrypt v1.1.8
|
||||
|
||||
v1.1.7:
|
||||
- Added support for zstd-compressed layers
|
||||
- Update to ocicrypt v1.1.6 for zstd-related dependencies
|
||||
- Update to containerd v1.6.8
|
||||
- Sync'ed ctr-enc with upstream ctr changes to import command
|
||||
- Add support for --all-platforms to encrypt command of ctr-enc
|
||||
|
||||
v1.1.6:
|
||||
- Update to ocicrypt v1.1.5 for yaml v3.0 dependency
|
||||
- Update to containerd v1.6.6 for runc v1.1.2 dependency
|
||||
|
||||
v1.1.5:
|
||||
- Update to ocicrypt v1.1.4; sha256 is the default now for padding in OAEP
|
||||
for pkcs11; Set OCICRYPT_OAEP_HASHALG=sha1 environment variable to force
|
||||
sha1 usage, which is required for example for SoftHSM 2.6.1.
|
||||
|
||||
v1.1.4:
|
||||
- Fixed issue in CheckAuthorization() callpath for images with a ManifestList
|
||||
- CVE-2022-24778
|
||||
- Fix: https://github.com/containerd/imgcrypt/commit/6fdd9818a4d8142107b7ecd767d839c9707700d9
|
||||
- Added test case covering this
|
||||
- Updated to ocicrypt 1.1.3
|
||||
- Updated to containerd 1.6.1
|
||||
|
||||
v1.1.3:
|
||||
- Release v1.1.3 addresses issue #62 due to re-tagging of v1.1.2
|
||||
- docs: update referenced containerd project branch to main
|
||||
- Update linter to match containerd repo
|
||||
- Update CI golang version
|
||||
- Updated to containerd 1.5.8
|
||||
|
||||
v1.1.2:
|
||||
- Decouple CreateCryptoConfig() from github.com/urfave/cli
|
||||
- Updated to containerd 1.5.7
|
||||
- Implemented ConvertFunc for image en- and decryption
|
||||
- Replace pkg/errors with errors package
|
||||
- Updated to ocicrypt 1.1.2
|
||||
- Sync'ed ctr-enc with ctr of containerd-1.5.0
|
||||
|
||||
v1.1.1:
|
||||
- rebased on ocicrypt 1.1.1
|
||||
|
||||
v1.1.0:
|
||||
- rebased on ocicrypt 1.1.0
|
||||
- added pkcs11 support; experimental
|
||||
- added keyprovider support
|
191
vendor/github.com/containerd/imgcrypt/LICENSE
generated
vendored
Normal file
191
vendor/github.com/containerd/imgcrypt/LICENSE
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright The containerd Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
9
vendor/github.com/containerd/imgcrypt/MAINTAINERS
generated
vendored
Normal file
9
vendor/github.com/containerd/imgcrypt/MAINTAINERS
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# imgcrypt maintainers
|
||||
#
|
||||
# As a containerd sub-project, containerd maintainers are also included from https://github.com/containerd/project/blob/main/MAINTAINERS.
|
||||
# See https://github.com/containerd/project/blob/main/GOVERNANCE.md for description of maintainer role
|
||||
#
|
||||
# MAINTAINERS
|
||||
# GitHub ID, Name, Email address
|
||||
stefanberger, Stefan Berger, stefanb@linux.ibm.com
|
||||
lumjjb, Brandon Lum, lumjjb@gmail.com
|
67
vendor/github.com/containerd/imgcrypt/Makefile
generated
vendored
Normal file
67
vendor/github.com/containerd/imgcrypt/Makefile
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
# Copyright The containerd Authors.
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
# Base path used to install.
|
||||
DESTDIR ?= /usr/local
|
||||
|
||||
VERSION=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always)
|
||||
|
||||
CTR_LDFLAGS=-ldflags '-X github.com/containerd/containerd/v2/version.Version=$(VERSION)'
|
||||
COMMANDS=ctd-decoder ctr-enc
|
||||
RELEASE_COMMANDS=ctd-decoder
|
||||
|
||||
BINARIES=$(addprefix bin/,$(COMMANDS))
|
||||
RELEASE_BINARIES=$(addprefix bin/,$(RELEASE_COMMANDS))
|
||||
|
||||
.PHONY: check build ctd-decoder
|
||||
|
||||
all: build
|
||||
|
||||
build: $(BINARIES)
|
||||
|
||||
FORCE:
|
||||
|
||||
bin/ctd-decoder: cmd/ctd-decoder FORCE
|
||||
cd cmd && go build -o ../$@ -v ./ctd-decoder/
|
||||
|
||||
bin/ctr-enc: cmd/ctr FORCE
|
||||
cd cmd && go build -o ../$@ ${CTR_LDFLAGS} -v ./ctr/
|
||||
|
||||
check:
|
||||
@echo "$@"
|
||||
@golangci-lint run
|
||||
@script/check_format.sh
|
||||
|
||||
install:
|
||||
@echo "$@"
|
||||
@mkdir -p $(DESTDIR)/bin
|
||||
@install $(BINARIES) $(DESTDIR)/bin
|
||||
|
||||
containerd-release:
|
||||
@echo "$@"
|
||||
@mkdir -p $(DESTDIR)/bin
|
||||
@install $(RELEASE_BINARIES) $(DESTDIR)/bin
|
||||
|
||||
uninstall:
|
||||
@echo "$@"
|
||||
@rm -f $(addprefix $(DESTDIR)/bin/,$(notdir $(BINARIES)))
|
||||
|
||||
clean:
|
||||
@echo "$@"
|
||||
@rm -f $(BINARIES)
|
||||
|
||||
test:
|
||||
@echo "$@"
|
||||
@go test ./...
|
108
vendor/github.com/containerd/imgcrypt/README.md
generated
vendored
Normal file
108
vendor/github.com/containerd/imgcrypt/README.md
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
# imgcrypt image encryption library and command line tool
|
||||
|
||||
Project `imgcrypt` is a non-core subproject of containerd.
|
||||
|
||||
The `imgcrypt` library provides API extensions for containerd to support encrypted container images and implements
|
||||
the `ctd-decoder` command line tool for use by containerd to decrypt encrypted container images. An extended version
|
||||
of containerd's `ctr` tool (`ctr-enc`) with support for encrypting and decrypting container images is also provided.
|
||||
|
||||
`imgcrypt` relies on the [`ocicrypt`](https://github.com/containers/ocicrypt) library for crypto functions on image layers.
|
||||
|
||||
# Usage
|
||||
|
||||
`imgcrypt` requires containerd 1.3 or later. Containerd 1.4 or later is required when used with Kubernetes.
|
||||
For configuration instructions for kubernetes, please consult the [CRI decryption document](https://github.com/containerd/containerd/blob/main/docs/cri/decryption.md).
|
||||
|
||||
Build and install `imgcrypt`:
|
||||
|
||||
```
|
||||
# make
|
||||
# sudo make install
|
||||
```
|
||||
|
||||
Start containerd with a configuration file that looks as follows. To avoid interference with a containerd from a Docker
|
||||
installation we use /tmp for directories. Also, we build containerd 1.3 from the source but do not install it.
|
||||
|
||||
```
|
||||
# cat config.toml
|
||||
version = 2
|
||||
disabled_plugins = ["io.containerd.grpc.v1.cri"]
|
||||
root = "/tmp/var/lib/containerd"
|
||||
state = "/tmp/run/containerd"
|
||||
[grpc]
|
||||
address = "/tmp/run/containerd/containerd.sock"
|
||||
uid = 0
|
||||
gid = 0
|
||||
[stream_processors]
|
||||
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
|
||||
accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
|
||||
returns = "application/vnd.oci.image.layer.v1.tar+gzip"
|
||||
path = "/usr/local/bin/ctd-decoder"
|
||||
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar.zstd"]
|
||||
accepts = ["application/vnd.oci.image.layer.v1.tar+zstd+encrypted"]
|
||||
returns = "application/vnd.oci.image.layer.v1.tar+zstd"
|
||||
path = "/usr/local/bin/ctd-decoder"
|
||||
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
|
||||
accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
|
||||
returns = "application/vnd.oci.image.layer.v1.tar"
|
||||
path = "/usr/local/bin/ctd-decoder"
|
||||
|
||||
# sudo ~/src/github.com/containerd/containerd/bin/containerd -c config.toml
|
||||
```
|
||||
|
||||
Create an RSA key pair using the openssl command line tool and encrypted an image:
|
||||
|
||||
```
|
||||
# openssl genrsa -out mykey.pem
|
||||
Generating RSA private key, 2048 bit long modulus (2 primes)
|
||||
...............................................+++++
|
||||
............................+++++
|
||||
e is 65537 (0x010001)
|
||||
# openssl rsa -in mykey.pem -pubout -out mypubkey.pem
|
||||
writing RSA key
|
||||
# sudo chmod 0666 /tmp/run/containerd/containerd.sock
|
||||
# CTR="/usr/local/bin/ctr-enc -a /tmp/run/containerd/containerd.sock"
|
||||
# $CTR images pull --all-platforms docker.io/library/bash:latest
|
||||
[...]
|
||||
# $CTR images layerinfo --platform linux/amd64 docker.io/library/bash:latest
|
||||
# DIGEST PLATFORM SIZE ENCRYPTION RECIPIENTS
|
||||
0 sha256:9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609 linux/amd64 2789669
|
||||
1 sha256:7dd01fd971d4ec7058c5636a505327b24e5fc8bd7f62816a9d518472bd9b15c0 linux/amd64 3174665
|
||||
2 sha256:691cfbca522787898c8b37f063dd20e5524e7d103e1a3b298bd2e2b8da54faf5 linux/amd64 340
|
||||
# $CTR images encrypt --recipient jwe:mypubkey.pem --platform linux/amd64 docker.io/library/bash:latest bash.enc:latest
|
||||
Encrypting docker.io/library/bash:latest to bash.enc:latest
|
||||
$ $CTR images layerinfo --platform linux/amd64 bash.enc:latest
|
||||
# DIGEST PLATFORM SIZE ENCRYPTION RECIPIENTS
|
||||
0 sha256:360be141b01f69b25427a9085b36ba8ad7d7a335449013fa6b32c1ecb894ab5b linux/amd64 2789669 jwe [jwe]
|
||||
1 sha256:ac601e66cdd275ee0e10afead03a2722e153a60982122d2d369880ea54fe82f8 linux/amd64 3174665 jwe [jwe]
|
||||
2 sha256:41e47064fd00424e328915ad2f7f716bd86ea2d0d8315edaf33ecaa6a2464530 linux/amd64 340 jwe [jwe]
|
||||
```
|
||||
|
||||
Start a local image registry so we can push the encrypted image to it. A recent versions of the registry is required
|
||||
to accept encrypted container images.
|
||||
```
|
||||
# docker pull registry:latest
|
||||
# docker run -d -p 5000:5000 --restart=always --name registry registry
|
||||
```
|
||||
|
||||
Push the encrypted image to the local registry, pull it using `ctr-enc`, and then run the image.
|
||||
```
|
||||
# $CTR images tag bash.enc:latest localhost:5000/bash.enc:latest
|
||||
# $CTR images push localhost:5000/bash.enc:latest
|
||||
# $CTR images rm localhost:5000/bash.enc:latest bash.enc:latest
|
||||
# $CTR images pull localhost:5000/bash.enc:latest
|
||||
# sudo $CTR run --rm localhost:5000/bash.enc:latest test echo 'Hello World!'
|
||||
ctr: you are not authorized to use this image: missing private key needed for decryption
|
||||
# sudo $CTR run --rm --key mykey.pem localhost:5000/bash.enc:latest test echo 'Hello World!'
|
||||
Hello World!
|
||||
```
|
||||
|
||||
## Project details
|
||||
|
||||
**imgcrypt** is a non-core containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
||||
As a containerd sub-project, you will find the:
|
||||
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
|
||||
* [Maintainers](MAINTAINERS),
|
||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
|
||||
|
||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
83
vendor/github.com/containerd/imgcrypt/images/encryption/client.go
generated
vendored
Normal file
83
vendor/github.com/containerd/imgcrypt/images/encryption/client.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package encryption
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
containerd "github.com/containerd/containerd/v2/client"
|
||||
"github.com/containerd/containerd/v2/core/containers"
|
||||
"github.com/containerd/containerd/v2/core/diff"
|
||||
"github.com/containerd/errdefs"
|
||||
"github.com/containerd/imgcrypt"
|
||||
"github.com/containerd/typeurl/v2"
|
||||
|
||||
encconfig "github.com/containers/ocicrypt/config"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// WithDecryptedUnpack allows to pass parameters the 'layertool' needs to the applier
|
||||
func WithDecryptedUnpack(data *imgcrypt.Payload) diff.ApplyOpt {
|
||||
return func(_ context.Context, desc ocispec.Descriptor, c *diff.ApplyConfig) error {
|
||||
data.Descriptor = desc
|
||||
anything, err := typeurl.MarshalAny(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal payload: %w", err)
|
||||
}
|
||||
|
||||
if c.ProcessorPayloads == nil {
|
||||
c.ProcessorPayloads = make(map[string]typeurl.Any, len(imgcrypt.PayloadToolIDs))
|
||||
}
|
||||
for _, id := range imgcrypt.PayloadToolIDs {
|
||||
c.ProcessorPayloads[id] = anything
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithUnpackConfigApplyOpts allows to pass an ApplyOpt
|
||||
func WithUnpackConfigApplyOpts(opt diff.ApplyOpt) containerd.UnpackOpt {
|
||||
return func(_ context.Context, uc *containerd.UnpackConfig) error {
|
||||
uc.ApplyOpts = append(uc.ApplyOpts, opt)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithUnpackOpts is used to add unpack options to the unpacker.
|
||||
func WithUnpackOpts(opts []containerd.UnpackOpt) containerd.RemoteOpt {
|
||||
return func(_ *containerd.Client, c *containerd.RemoteContext) error {
|
||||
c.UnpackOpts = append(c.UnpackOpts, opts...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithAuthorizationCheck checks the authorization of keys used for encrypted containers
|
||||
// be checked upon creation of a container
|
||||
func WithAuthorizationCheck(dc *encconfig.DecryptConfig) containerd.NewContainerOpts {
|
||||
return func(ctx context.Context, client *containerd.Client, c *containers.Container) error {
|
||||
image, err := client.ImageService().Get(ctx, c.Image)
|
||||
if errdefs.IsNotFound(err) {
|
||||
// allow creation of container without a existing image
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return CheckAuthorization(ctx, client.ContentStore(), image.Target, dc)
|
||||
}
|
||||
}
|
512
vendor/github.com/containerd/imgcrypt/images/encryption/encryption.go
generated
vendored
Normal file
512
vendor/github.com/containerd/imgcrypt/images/encryption/encryption.go
generated
vendored
Normal file
@ -0,0 +1,512 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package encryption
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
|
||||
"github.com/containerd/containerd/v2/core/content"
|
||||
"github.com/containerd/containerd/v2/core/images"
|
||||
"github.com/containerd/containerd/v2/core/images/converter"
|
||||
"github.com/containerd/errdefs"
|
||||
"github.com/containerd/platforms"
|
||||
|
||||
"github.com/containers/ocicrypt"
|
||||
encconfig "github.com/containers/ocicrypt/config"
|
||||
encocispec "github.com/containers/ocicrypt/spec"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type cryptoOp int
|
||||
|
||||
const (
|
||||
cryptoOpEncrypt cryptoOp = iota
|
||||
cryptoOpDecrypt = iota
|
||||
cryptoOpUnwrapOnly = iota
|
||||
)
|
||||
|
||||
// LayerFilter allows to select Layers by certain criteria
|
||||
type LayerFilter func(desc ocispec.Descriptor) bool
|
||||
|
||||
// isLocalPlatform determines whether the given platform matches the local one
|
||||
func isLocalPlatform(platform *ocispec.Platform) bool {
|
||||
matcher := platforms.NewMatcher(*platform)
|
||||
|
||||
return matcher.Match(platforms.DefaultSpec())
|
||||
}
|
||||
|
||||
// IsEncryptedDiff returns true if mediaType is a known encrypted media type.
|
||||
func IsEncryptedDiff(_ context.Context, mediaType string) bool {
|
||||
switch mediaType {
|
||||
case encocispec.MediaTypeLayerZstdEnc, encocispec.MediaTypeLayerGzipEnc, encocispec.MediaTypeLayerEnc:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasEncryptedLayer returns true if any LayerInfo indicates that the layer is encrypted
|
||||
func HasEncryptedLayer(ctx context.Context, layerInfos []ocispec.Descriptor) bool {
|
||||
for i := 0; i < len(layerInfos); i++ {
|
||||
if IsEncryptedDiff(ctx, layerInfos[i].MediaType) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// encryptLayer encrypts the layer using the CryptoConfig and creates a new OCI Descriptor.
|
||||
// A call to this function may also only manipulate the wrapped keys list.
|
||||
// The caller is expected to store the returned encrypted data and OCI Descriptor
|
||||
func encryptLayer(cc *encconfig.CryptoConfig, dataReader content.ReaderAt, desc ocispec.Descriptor) (ocispec.Descriptor, io.Reader, ocicrypt.EncryptLayerFinalizer, error) {
|
||||
var (
|
||||
size int64
|
||||
d digest.Digest
|
||||
err error
|
||||
)
|
||||
|
||||
encLayerReader, encLayerFinalizer, err := ocicrypt.EncryptLayer(cc.EncryptConfig, ocicrypt.ReaderFromReaderAt(dataReader), desc)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, nil, nil, err
|
||||
}
|
||||
|
||||
// were data touched ?
|
||||
if encLayerReader != nil {
|
||||
size = 0
|
||||
d = ""
|
||||
} else {
|
||||
size = desc.Size
|
||||
d = desc.Digest
|
||||
}
|
||||
|
||||
newDesc := ocispec.Descriptor{
|
||||
Digest: d,
|
||||
Size: size,
|
||||
Platform: desc.Platform,
|
||||
}
|
||||
|
||||
switch desc.MediaType {
|
||||
case images.MediaTypeDockerSchema2LayerGzip:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerGzipEnc
|
||||
case images.MediaTypeDockerSchema2Layer:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerEnc
|
||||
case encocispec.MediaTypeLayerGzipEnc:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerGzipEnc
|
||||
case encocispec.MediaTypeLayerZstdEnc:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerZstdEnc
|
||||
case encocispec.MediaTypeLayerEnc:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerEnc
|
||||
|
||||
// TODO: Mediatypes to be added in ocispec
|
||||
case ocispec.MediaTypeImageLayerGzip:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerGzipEnc
|
||||
case ocispec.MediaTypeImageLayerZstd:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerZstdEnc
|
||||
case ocispec.MediaTypeImageLayer:
|
||||
newDesc.MediaType = encocispec.MediaTypeLayerEnc
|
||||
|
||||
default:
|
||||
return ocispec.Descriptor{}, nil, nil, fmt.Errorf("unsupporter layer MediaType: %s", desc.MediaType)
|
||||
}
|
||||
|
||||
return newDesc, encLayerReader, encLayerFinalizer, nil
|
||||
}
|
||||
|
||||
// DecryptLayer decrypts the layer using the DecryptConfig and creates a new OCI Descriptor.
|
||||
// The caller is expected to store the returned plain data and OCI Descriptor
|
||||
func DecryptLayer(dc *encconfig.DecryptConfig, dataReader io.Reader, desc ocispec.Descriptor, unwrapOnly bool) (ocispec.Descriptor, io.Reader, digest.Digest, error) {
|
||||
resultReader, layerDigest, err := ocicrypt.DecryptLayer(dc, dataReader, desc, unwrapOnly)
|
||||
if err != nil || unwrapOnly {
|
||||
return ocispec.Descriptor{}, nil, "", err
|
||||
}
|
||||
|
||||
newDesc := ocispec.Descriptor{
|
||||
Size: 0,
|
||||
Platform: desc.Platform,
|
||||
}
|
||||
|
||||
switch desc.MediaType {
|
||||
case encocispec.MediaTypeLayerGzipEnc:
|
||||
newDesc.MediaType = images.MediaTypeDockerSchema2LayerGzip
|
||||
case encocispec.MediaTypeLayerZstdEnc:
|
||||
newDesc.MediaType = ocispec.MediaTypeImageLayerZstd
|
||||
case encocispec.MediaTypeLayerEnc:
|
||||
newDesc.MediaType = images.MediaTypeDockerSchema2Layer
|
||||
default:
|
||||
return ocispec.Descriptor{}, nil, "", fmt.Errorf("unsupporter layer MediaType: %s", desc.MediaType)
|
||||
}
|
||||
return newDesc, resultReader, layerDigest, nil
|
||||
}
|
||||
|
||||
// decryptLayer decrypts the layer using the CryptoConfig and creates a new OCI Descriptor.
|
||||
// The caller is expected to store the returned plain data and OCI Descriptor
|
||||
func decryptLayer(cc *encconfig.CryptoConfig, dataReader content.ReaderAt, desc ocispec.Descriptor, unwrapOnly bool) (ocispec.Descriptor, io.Reader, error) {
|
||||
resultReader, d, err := ocicrypt.DecryptLayer(cc.DecryptConfig, ocicrypt.ReaderFromReaderAt(dataReader), desc, unwrapOnly)
|
||||
if err != nil || unwrapOnly {
|
||||
return ocispec.Descriptor{}, nil, err
|
||||
}
|
||||
|
||||
newDesc := ocispec.Descriptor{
|
||||
Digest: d,
|
||||
Size: 0,
|
||||
Platform: desc.Platform,
|
||||
}
|
||||
|
||||
switch desc.MediaType {
|
||||
case encocispec.MediaTypeLayerGzipEnc:
|
||||
newDesc.MediaType = images.MediaTypeDockerSchema2LayerGzip
|
||||
case encocispec.MediaTypeLayerZstdEnc:
|
||||
newDesc.MediaType = ocispec.MediaTypeImageLayerZstd
|
||||
case encocispec.MediaTypeLayerEnc:
|
||||
newDesc.MediaType = images.MediaTypeDockerSchema2Layer
|
||||
default:
|
||||
return ocispec.Descriptor{}, nil, fmt.Errorf("unsupporter layer MediaType: %s", desc.MediaType)
|
||||
}
|
||||
return newDesc, resultReader, nil
|
||||
}
|
||||
|
||||
// cryptLayer handles the changes due to encryption or decryption of a layer
|
||||
func cryptLayer(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, cryptoOp cryptoOp) (ocispec.Descriptor, error) {
|
||||
var (
|
||||
resultReader io.Reader
|
||||
newDesc ocispec.Descriptor
|
||||
encLayerFinalizer ocicrypt.EncryptLayerFinalizer
|
||||
)
|
||||
|
||||
dataReader, err := cs.ReaderAt(ctx, desc)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
defer dataReader.Close()
|
||||
|
||||
if cryptoOp == cryptoOpEncrypt {
|
||||
newDesc, resultReader, encLayerFinalizer, err = encryptLayer(cc, dataReader, desc)
|
||||
} else {
|
||||
newDesc, resultReader, err = decryptLayer(cc, dataReader, desc, cryptoOp == cryptoOpUnwrapOnly)
|
||||
}
|
||||
if err != nil || cryptoOp == cryptoOpUnwrapOnly {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
|
||||
newDesc.Annotations = ocicrypt.FilterOutAnnotations(desc.Annotations)
|
||||
|
||||
// some operations, such as changing recipients, may not touch the layer at all
|
||||
if resultReader != nil {
|
||||
var ref string
|
||||
// If we have the digest, write blob with checks
|
||||
haveDigest := newDesc.Digest.String() != ""
|
||||
if haveDigest {
|
||||
ref = fmt.Sprintf("layer-%s", newDesc.Digest.String())
|
||||
} else {
|
||||
ref = fmt.Sprintf("blob-%d-%d", rand.Int(), rand.Int())
|
||||
}
|
||||
|
||||
if haveDigest {
|
||||
if err := content.WriteBlob(ctx, cs, ref, resultReader, newDesc); err != nil {
|
||||
return ocispec.Descriptor{}, fmt.Errorf("failed to write config: %w", err)
|
||||
}
|
||||
} else {
|
||||
newDesc.Digest, newDesc.Size, err = ingestReader(ctx, cs, ref, resultReader)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// After performing encryption, call finalizer to get annotations
|
||||
if encLayerFinalizer != nil {
|
||||
annotations, err := encLayerFinalizer()
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, fmt.Errorf("error getting annotations from encLayer finalizer: %w", err)
|
||||
}
|
||||
for k, v := range annotations {
|
||||
newDesc.Annotations[k] = v
|
||||
}
|
||||
}
|
||||
return newDesc, err
|
||||
}
|
||||
|
||||
func ingestReader(ctx context.Context, cs content.Ingester, ref string, r io.Reader) (digest.Digest, int64, error) {
|
||||
cw, err := content.OpenWriter(ctx, cs, content.WithRef(ref))
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("failed to open writer: %w", err)
|
||||
}
|
||||
defer cw.Close()
|
||||
|
||||
if _, err := content.CopyReader(cw, r); err != nil {
|
||||
return "", 0, fmt.Errorf("copy failed: %w", err)
|
||||
}
|
||||
|
||||
st, err := cw.Status()
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("failed to get state: %w", err)
|
||||
}
|
||||
|
||||
if err := cw.Commit(ctx, st.Offset, ""); err != nil {
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return "", 0, fmt.Errorf("failed commit on ref %q: %w", ref, err)
|
||||
}
|
||||
}
|
||||
|
||||
return cw.Digest(), st.Offset, nil
|
||||
}
|
||||
|
||||
// Encrypt or decrypt all the Children of a given descriptor
|
||||
func cryptChildren(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter, cryptoOp cryptoOp, _ *ocispec.Platform) (ocispec.Descriptor, bool, error) {
|
||||
children, err := images.Children(ctx, cs, desc)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
return desc, false, nil
|
||||
}
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
|
||||
var newLayers []ocispec.Descriptor
|
||||
var config ocispec.Descriptor
|
||||
modified := false
|
||||
|
||||
for _, child := range children {
|
||||
// we only encrypt child layers and have to update their parents if encryption happened
|
||||
switch child.MediaType {
|
||||
case images.MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig:
|
||||
config = child
|
||||
case images.MediaTypeDockerSchema2LayerGzip, images.MediaTypeDockerSchema2Layer,
|
||||
ocispec.MediaTypeImageLayerGzip, ocispec.MediaTypeImageLayer,
|
||||
ocispec.MediaTypeImageLayerZstd:
|
||||
if cryptoOp == cryptoOpEncrypt && lf(child) {
|
||||
nl, err := cryptLayer(ctx, cs, child, cc, cryptoOp)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
modified = true
|
||||
newLayers = append(newLayers, nl)
|
||||
} else {
|
||||
newLayers = append(newLayers, child)
|
||||
}
|
||||
case encocispec.MediaTypeLayerGzipEnc, encocispec.MediaTypeLayerZstdEnc, encocispec.MediaTypeLayerEnc:
|
||||
// this one can be decrypted but also its recipients list changed
|
||||
if lf(child) {
|
||||
nl, err := cryptLayer(ctx, cs, child, cc, cryptoOp)
|
||||
if err != nil || cryptoOp == cryptoOpUnwrapOnly {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
modified = true
|
||||
newLayers = append(newLayers, nl)
|
||||
} else {
|
||||
newLayers = append(newLayers, child)
|
||||
}
|
||||
case images.MediaTypeDockerSchema2LayerForeign, images.MediaTypeDockerSchema2LayerForeignGzip, "application/vnd.in-toto+json":
|
||||
// never encrypt/decrypt
|
||||
newLayers = append(newLayers, child)
|
||||
default:
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("bad/unhandled MediaType %s in encryptChildren", child.MediaType)
|
||||
}
|
||||
}
|
||||
|
||||
if modified && len(newLayers) > 0 {
|
||||
newManifest := ocispec.Manifest{
|
||||
Versioned: specs.Versioned{
|
||||
SchemaVersion: 2,
|
||||
},
|
||||
Config: config,
|
||||
Layers: newLayers,
|
||||
}
|
||||
|
||||
mb, err := json.MarshalIndent(newManifest, "", " ")
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("failed to marshal image: %w", err)
|
||||
}
|
||||
|
||||
newDesc := ocispec.Descriptor{
|
||||
MediaType: ocispec.MediaTypeImageManifest,
|
||||
Size: int64(len(mb)),
|
||||
Digest: digest.Canonical.FromBytes(mb),
|
||||
Platform: desc.Platform,
|
||||
}
|
||||
|
||||
labels := map[string]string{}
|
||||
labels["containerd.io/gc.ref.content.0"] = newManifest.Config.Digest.String()
|
||||
for i, ch := range newManifest.Layers {
|
||||
labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i+1)] = ch.Digest.String()
|
||||
}
|
||||
|
||||
ref := fmt.Sprintf("manifest-%s", newDesc.Digest.String())
|
||||
|
||||
if err := content.WriteBlob(ctx, cs, ref, bytes.NewReader(mb), newDesc, content.WithLabels(labels)); err != nil {
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("failed to write config: %w", err)
|
||||
}
|
||||
return newDesc, true, nil
|
||||
}
|
||||
|
||||
return desc, modified, nil
|
||||
}
|
||||
|
||||
// cryptManifest encrypts or decrypts the children of a top level manifest
|
||||
func cryptManifest(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter, cryptoOp cryptoOp) (ocispec.Descriptor, bool, error) {
|
||||
p, err := content.ReadBlob(ctx, cs, desc)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
var manifest ocispec.Manifest
|
||||
if err := json.Unmarshal(p, &manifest); err != nil {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
platform := platforms.DefaultSpec()
|
||||
newDesc, modified, err := cryptChildren(ctx, cs, desc, cc, lf, cryptoOp, &platform)
|
||||
if err != nil || cryptoOp == cryptoOpUnwrapOnly {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
return newDesc, modified, nil
|
||||
}
|
||||
|
||||
// cryptManifestList encrypts or decrypts the children of a top level manifest list
|
||||
func cryptManifestList(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter, cryptoOp cryptoOp) (ocispec.Descriptor, bool, error) {
|
||||
// read the index; if any layer is encrypted and any manifests change we will need to rewrite it
|
||||
b, err := content.ReadBlob(ctx, cs, desc)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
|
||||
var index ocispec.Index
|
||||
if err := json.Unmarshal(b, &index); err != nil {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
|
||||
var newManifests []ocispec.Descriptor
|
||||
modified := false
|
||||
for _, manifest := range index.Manifests {
|
||||
if cryptoOp == cryptoOpUnwrapOnly && !isLocalPlatform(manifest.Platform) {
|
||||
continue
|
||||
}
|
||||
newManifest, m, err := cryptChildren(ctx, cs, manifest, cc, lf, cryptoOp, manifest.Platform)
|
||||
if err != nil || cryptoOp == cryptoOpUnwrapOnly {
|
||||
return ocispec.Descriptor{}, false, err
|
||||
}
|
||||
if m {
|
||||
modified = true
|
||||
}
|
||||
newManifests = append(newManifests, newManifest)
|
||||
}
|
||||
if cryptoOp == cryptoOpUnwrapOnly {
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("No manifest found for local platform")
|
||||
}
|
||||
|
||||
if modified {
|
||||
// we need to update the index
|
||||
newIndex := ocispec.Index{
|
||||
Versioned: index.Versioned,
|
||||
Manifests: newManifests,
|
||||
}
|
||||
|
||||
mb, err := json.MarshalIndent(newIndex, "", " ")
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("failed to marshal index: %w", err)
|
||||
}
|
||||
|
||||
newDesc := ocispec.Descriptor{
|
||||
MediaType: ocispec.MediaTypeImageIndex,
|
||||
Size: int64(len(mb)),
|
||||
Digest: digest.Canonical.FromBytes(mb),
|
||||
}
|
||||
|
||||
labels := map[string]string{}
|
||||
for i, m := range newIndex.Manifests {
|
||||
labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = m.Digest.String()
|
||||
}
|
||||
|
||||
ref := fmt.Sprintf("index-%s", newDesc.Digest.String())
|
||||
|
||||
if err = content.WriteBlob(ctx, cs, ref, bytes.NewReader(mb), newDesc, content.WithLabels(labels)); err != nil {
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("failed to write index: %w", err)
|
||||
}
|
||||
return newDesc, true, nil
|
||||
}
|
||||
|
||||
return desc, false, nil
|
||||
}
|
||||
|
||||
// cryptImage is the dispatcher to encrypt/decrypt an image; it accepts either an OCI descriptor
|
||||
// representing a manifest list or a single manifest
|
||||
func cryptImage(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter, cryptoOp cryptoOp) (ocispec.Descriptor, bool, error) {
|
||||
if cc == nil {
|
||||
return ocispec.Descriptor{}, false, errors.New("invalid argument: CryptoConfig must not be nil")
|
||||
}
|
||||
switch desc.MediaType {
|
||||
case ocispec.MediaTypeImageIndex, images.MediaTypeDockerSchema2ManifestList:
|
||||
return cryptManifestList(ctx, cs, desc, cc, lf, cryptoOp)
|
||||
case ocispec.MediaTypeImageManifest, images.MediaTypeDockerSchema2Manifest:
|
||||
return cryptManifest(ctx, cs, desc, cc, lf, cryptoOp)
|
||||
default:
|
||||
return ocispec.Descriptor{}, false, fmt.Errorf("unhandled media type: %s", desc.MediaType)
|
||||
}
|
||||
}
|
||||
|
||||
// EncryptImage encrypts an image; it accepts either an OCI descriptor representing a manifest list or a single manifest
|
||||
func EncryptImage(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter) (ocispec.Descriptor, bool, error) {
|
||||
return cryptImage(ctx, cs, desc, cc, lf, cryptoOpEncrypt)
|
||||
}
|
||||
|
||||
// DecryptImage decrypts an image; it accepts either an OCI descriptor representing a manifest list or a single manifest
|
||||
func DecryptImage(ctx context.Context, cs content.Store, desc ocispec.Descriptor, cc *encconfig.CryptoConfig, lf LayerFilter) (ocispec.Descriptor, bool, error) {
|
||||
return cryptImage(ctx, cs, desc, cc, lf, cryptoOpDecrypt)
|
||||
}
|
||||
|
||||
// GetImageEncryptConverter returns a converter function for image encryption
|
||||
func GetImageEncryptConverter(cc *encconfig.CryptoConfig, lf LayerFilter) converter.ConvertFunc {
|
||||
return func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {
|
||||
newDesc, _, err := EncryptImage(ctx, cs, desc, cc, lf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &newDesc, nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetImageDecryptConverter returns a converter function for image decryption
|
||||
func GetImageDecryptConverter(cc *encconfig.CryptoConfig, lf LayerFilter) converter.ConvertFunc {
|
||||
return func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {
|
||||
newDesc, _, err := DecryptImage(ctx, cs, desc, cc, lf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &newDesc, nil
|
||||
}
|
||||
}
|
||||
|
||||
// CheckAuthorization checks whether a user has the right keys to be allowed to access an image (every layer)
|
||||
// It takes decrypting of the layers only as far as decrypting the asymmetrically encrypted data
|
||||
// The decryption is only done for the current platform
|
||||
func CheckAuthorization(ctx context.Context, cs content.Store, desc ocispec.Descriptor, dc *encconfig.DecryptConfig) error {
|
||||
cc := encconfig.InitDecryption(dc.Parameters)
|
||||
|
||||
lf := func(desc ocispec.Descriptor) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
_, _, err := cryptImage(ctx, cs, desc, &cc, lf, cryptoOpUnwrapOnly)
|
||||
if err != nil {
|
||||
return fmt.Errorf("you are not authorized to use this image: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
44
vendor/github.com/containerd/imgcrypt/payload.go
generated
vendored
Normal file
44
vendor/github.com/containerd/imgcrypt/payload.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package imgcrypt
|
||||
|
||||
import (
|
||||
"github.com/containerd/typeurl/v2"
|
||||
|
||||
encconfig "github.com/containers/ocicrypt/config"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
PayloadURI = "io.containerd.ocicrypt.v1.Payload"
|
||||
)
|
||||
|
||||
var PayloadToolIDs = []string{
|
||||
"io.containerd.ocicrypt.decoder.v1.tar",
|
||||
"io.containerd.ocicrypt.decoder.v1.tar.gzip",
|
||||
}
|
||||
|
||||
func init() {
|
||||
typeurl.Register(&Payload{}, PayloadURI)
|
||||
}
|
||||
|
||||
// Payload holds data that the external layer decryption tool
|
||||
// needs for decrypting a layer
|
||||
type Payload struct {
|
||||
DecryptConfig encconfig.DecryptConfig
|
||||
Descriptor ocispec.Descriptor
|
||||
}
|
1
vendor/github.com/containers/ocicrypt/.gitignore
generated
vendored
Normal file
1
vendor/github.com/containers/ocicrypt/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
*~
|
35
vendor/github.com/containers/ocicrypt/.golangci.yml
generated
vendored
Normal file
35
vendor/github.com/containers/ocicrypt/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
linters:
|
||||
enable:
|
||||
- depguard
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- gofmt
|
||||
- goimports
|
||||
- revive
|
||||
- ineffassign
|
||||
- vet
|
||||
- unused
|
||||
- misspell
|
||||
|
||||
linters-settings:
|
||||
depguard:
|
||||
rules:
|
||||
main:
|
||||
files:
|
||||
- $all
|
||||
deny:
|
||||
- pkg: "io/ioutil"
|
||||
|
||||
revive:
|
||||
severity: error
|
||||
rules:
|
||||
- name: indent-error-flow
|
||||
severity: warning
|
||||
disabled: false
|
||||
|
||||
- name: error-strings
|
||||
disabled: false
|
||||
|
||||
staticcheck:
|
||||
# Suppress reports of deprecated packages
|
||||
checks: ["-SA1019"]
|
10
vendor/github.com/containers/ocicrypt/ADOPTERS.md
generated
vendored
Normal file
10
vendor/github.com/containers/ocicrypt/ADOPTERS.md
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
Below are list of adopters of the `ocicrypt` library or supports use of OCI encrypted images:
|
||||
- [skopeo](https://github.com/containers/skopeo)
|
||||
- [buildah](https://github.com/containers/buildah)
|
||||
- [containerd](https://github.com/containerd/imgcrypt)
|
||||
- [nerdctl](https://github.com/containerd/nerdctl)
|
||||
- [distribution](https://github.com/distribution/distribution)
|
||||
|
||||
Below are the list of projects that are in the process of adopting support:
|
||||
- [quay](https://github.com/quay/quay)
|
||||
- [kata-containers](https://github.com/kata-containers/kata-containers)
|
3
vendor/github.com/containers/ocicrypt/CODE-OF-CONDUCT.md
generated
vendored
Normal file
3
vendor/github.com/containers/ocicrypt/CODE-OF-CONDUCT.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
## The OCIcrypt Library Project Community Code of Conduct
|
||||
|
||||
The OCIcrypt Library project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/main/CODE-OF-CONDUCT.md).
|
189
vendor/github.com/containers/ocicrypt/LICENSE
generated
vendored
Normal file
189
vendor/github.com/containers/ocicrypt/LICENSE
generated
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
6
vendor/github.com/containers/ocicrypt/MAINTAINERS
generated
vendored
Normal file
6
vendor/github.com/containers/ocicrypt/MAINTAINERS
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# ocicrypt maintainers
|
||||
#
|
||||
# Github ID, Name, Email Address
|
||||
lumjjb, Brandon Lum, lumjjb@gmail.com
|
||||
stefanberger, Stefan Berger, stefanb@linux.ibm.com
|
||||
arronwy, Arron Wang, arron.wang@intel.com
|
35
vendor/github.com/containers/ocicrypt/Makefile
generated
vendored
Normal file
35
vendor/github.com/containers/ocicrypt/Makefile
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright The containerd Authors.
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
.PHONY: check build decoder generate-protobuf
|
||||
|
||||
all: build
|
||||
|
||||
FORCE:
|
||||
|
||||
check:
|
||||
golangci-lint run
|
||||
|
||||
build: vendor
|
||||
go build ./...
|
||||
|
||||
vendor:
|
||||
go mod tidy
|
||||
|
||||
test:
|
||||
go clean -testcache
|
||||
go test ./... -test.v
|
||||
|
||||
generate-protobuf:
|
||||
protoc -I utils/keyprovider/ utils/keyprovider/keyprovider.proto --go_out=plugins=grpc:utils/keyprovider
|
50
vendor/github.com/containers/ocicrypt/README.md
generated
vendored
Normal file
50
vendor/github.com/containers/ocicrypt/README.md
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
# OCIcrypt Library
|
||||
|
||||
The `ocicrypt` library is the OCI image spec implementation of container image encryption. More details of the spec can be seen in the [OCI repository](https://github.com/opencontainers/image-spec/pull/775). The purpose of this library is to encode spec structures and consts in code, as well as provide a consistent implementation of image encryption across container runtimes and build tools.
|
||||
|
||||
Consumers of OCIcrypt:
|
||||
|
||||
- [containerd/imgcrypt](https://github.com/containerd/imgcrypt)
|
||||
- [cri-o](https://github.com/cri-o/cri-o)
|
||||
- [skopeo](https://github.com/containers/skopeo)
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
There are various levels of usage for this library. The main consumers of these would be runtime/build tools, and a more specific use would be in the ability to extend cryptographic function.
|
||||
|
||||
### Runtime/Build tool usage
|
||||
|
||||
The general exposed interface a runtime/build tool would use, would be to perform encryption or decryption of layers:
|
||||
|
||||
```
|
||||
package "github.com/containers/ocicrypt"
|
||||
func EncryptLayer(ec *config.EncryptConfig, encOrPlainLayerReader io.Reader, desc ocispec.Descriptor) (io.Reader, EncryptLayerFinalizer, error)
|
||||
func DecryptLayer(dc *config.DecryptConfig, encLayerReader io.Reader, desc ocispec.Descriptor, unwrapOnly bool) (io.Reader, digest.Digest, error)
|
||||
```
|
||||
|
||||
The settings/parameters to these functions can be specified via creation of an encryption config with the `github.com/containers/ocicrypt/config` package. We note that because setting of annotations and other fields of the layer descriptor is done through various means in different runtimes/build tools, it is the responsibility of the caller to still ensure that the layer descriptor follows the OCI specification (i.e. encoding, setting annotations, etc.).
|
||||
|
||||
|
||||
### Crypto Agility and Extensibility
|
||||
|
||||
The implementation for both symmetric and asymmetric encryption used in this library are behind 2 main interfaces, which users can extend if need be. These are in the following packages:
|
||||
- github.com/containers/ocicrypt/blockcipher - LayerBlockCipher interface for block ciphers
|
||||
- github.com/containers/ocicrypt/keywrap - KeyWrapper interface for key wrapping
|
||||
|
||||
We note that adding interfaces here is risky outside the OCI spec is not recommended, unless for very specialized and confined usecases. Please open an issue or PR if there is a general usecase that could be added to the OCI spec.
|
||||
|
||||
|
||||
#### Keyprovider interface
|
||||
|
||||
As part of the keywrap interface, there is a [keyprovider](https://github.com/containers/ocicrypt/blob/main/docs/keyprovider.md) implementation that allows one to call out to a binary or service.
|
||||
|
||||
|
||||
## Security Issues
|
||||
|
||||
We consider security issues related to this library critical. Please report and security related issues by emailing maintainers in the [MAINTAINERS](MAINTAINERS) file.
|
||||
|
||||
|
||||
## Ocicrypt Pkcs11 Support
|
||||
|
||||
Ocicrypt Pkcs11 support is currently experiemental. For more details, please refer to the [this document](docs/pkcs11.md).
|
3
vendor/github.com/containers/ocicrypt/SECURITY.md
generated
vendored
Normal file
3
vendor/github.com/containers/ocicrypt/SECURITY.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
## Security and Disclosure Information Policy for the OCIcrypt Library Project
|
||||
|
||||
The OCIcrypt Library Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/main/SECURITY.md) for the Containers Projects.
|
161
vendor/github.com/containers/ocicrypt/blockcipher/blockcipher.go
generated
vendored
Normal file
161
vendor/github.com/containers/ocicrypt/blockcipher/blockcipher.go
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package blockcipher
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
// LayerCipherType is the ciphertype as specified in the layer metadata
|
||||
type LayerCipherType string
|
||||
|
||||
// TODO: Should be obtained from OCI spec once included
|
||||
const (
|
||||
AES256CTR LayerCipherType = "AES_256_CTR_HMAC_SHA256"
|
||||
)
|
||||
|
||||
// PrivateLayerBlockCipherOptions includes the information required to encrypt/decrypt
|
||||
// an image which are sensitive and should not be in plaintext
|
||||
type PrivateLayerBlockCipherOptions struct {
|
||||
// SymmetricKey represents the symmetric key used for encryption/decryption
|
||||
// This field should be populated by Encrypt/Decrypt calls
|
||||
SymmetricKey []byte `json:"symkey"`
|
||||
|
||||
// Digest is the digest of the original data for verification.
|
||||
// This is NOT populated by Encrypt/Decrypt calls
|
||||
Digest digest.Digest `json:"digest"`
|
||||
|
||||
// CipherOptions contains the cipher metadata used for encryption/decryption
|
||||
// This field should be populated by Encrypt/Decrypt calls
|
||||
CipherOptions map[string][]byte `json:"cipheroptions"`
|
||||
}
|
||||
|
||||
// PublicLayerBlockCipherOptions includes the information required to encrypt/decrypt
|
||||
// an image which are public and can be deduplicated in plaintext across multiple
|
||||
// recipients
|
||||
type PublicLayerBlockCipherOptions struct {
|
||||
// CipherType denotes the cipher type according to the list of OCI suppported
|
||||
// cipher types.
|
||||
CipherType LayerCipherType `json:"cipher"`
|
||||
|
||||
// Hmac contains the hmac string to help verify encryption
|
||||
Hmac []byte `json:"hmac"`
|
||||
|
||||
// CipherOptions contains the cipher metadata used for encryption/decryption
|
||||
// This field should be populated by Encrypt/Decrypt calls
|
||||
CipherOptions map[string][]byte `json:"cipheroptions"`
|
||||
}
|
||||
|
||||
// LayerBlockCipherOptions contains the public and private LayerBlockCipherOptions
|
||||
// required to encrypt/decrypt an image
|
||||
type LayerBlockCipherOptions struct {
|
||||
Public PublicLayerBlockCipherOptions
|
||||
Private PrivateLayerBlockCipherOptions
|
||||
}
|
||||
|
||||
// LayerBlockCipher returns a provider for encrypt/decrypt functionality
|
||||
// for handling the layer data for a specific algorithm
|
||||
type LayerBlockCipher interface {
|
||||
// GenerateKey creates a symmetric key
|
||||
GenerateKey() ([]byte, error)
|
||||
// Encrypt takes in layer data and returns the ciphertext and relevant LayerBlockCipherOptions
|
||||
Encrypt(layerDataReader io.Reader, opt LayerBlockCipherOptions) (io.Reader, Finalizer, error)
|
||||
// Decrypt takes in layer ciphertext data and returns the plaintext and relevant LayerBlockCipherOptions
|
||||
Decrypt(layerDataReader io.Reader, opt LayerBlockCipherOptions) (io.Reader, LayerBlockCipherOptions, error)
|
||||
}
|
||||
|
||||
// LayerBlockCipherHandler is the handler for encrypt/decrypt for layers
|
||||
type LayerBlockCipherHandler struct {
|
||||
cipherMap map[LayerCipherType]LayerBlockCipher
|
||||
}
|
||||
|
||||
// Finalizer is called after data blobs are written, and returns the LayerBlockCipherOptions for the encrypted blob
|
||||
type Finalizer func() (LayerBlockCipherOptions, error)
|
||||
|
||||
// GetOpt returns the value of the cipher option and if the option exists
|
||||
func (lbco LayerBlockCipherOptions) GetOpt(key string) (value []byte, ok bool) {
|
||||
if v, ok := lbco.Public.CipherOptions[key]; ok {
|
||||
return v, ok
|
||||
} else if v, ok := lbco.Private.CipherOptions[key]; ok {
|
||||
return v, ok
|
||||
} else {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func wrapFinalizerWithType(fin Finalizer, typ LayerCipherType) Finalizer {
|
||||
return func() (LayerBlockCipherOptions, error) {
|
||||
lbco, err := fin()
|
||||
if err != nil {
|
||||
return LayerBlockCipherOptions{}, err
|
||||
}
|
||||
lbco.Public.CipherType = typ
|
||||
return lbco, err
|
||||
}
|
||||
}
|
||||
|
||||
// Encrypt is the handler for the layer decryption routine
|
||||
func (h *LayerBlockCipherHandler) Encrypt(plainDataReader io.Reader, typ LayerCipherType) (io.Reader, Finalizer, error) {
|
||||
if c, ok := h.cipherMap[typ]; ok {
|
||||
sk, err := c.GenerateKey()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt := LayerBlockCipherOptions{
|
||||
Private: PrivateLayerBlockCipherOptions{
|
||||
SymmetricKey: sk,
|
||||
},
|
||||
}
|
||||
encDataReader, fin, err := c.Encrypt(plainDataReader, opt)
|
||||
if err == nil {
|
||||
fin = wrapFinalizerWithType(fin, typ)
|
||||
}
|
||||
return encDataReader, fin, err
|
||||
}
|
||||
return nil, nil, fmt.Errorf("unsupported cipher type: %s", typ)
|
||||
}
|
||||
|
||||
// Decrypt is the handler for the layer decryption routine
|
||||
func (h *LayerBlockCipherHandler) Decrypt(encDataReader io.Reader, opt LayerBlockCipherOptions) (io.Reader, LayerBlockCipherOptions, error) {
|
||||
typ := opt.Public.CipherType
|
||||
if typ == "" {
|
||||
return nil, LayerBlockCipherOptions{}, errors.New("no cipher type provided")
|
||||
}
|
||||
if c, ok := h.cipherMap[typ]; ok {
|
||||
return c.Decrypt(encDataReader, opt)
|
||||
}
|
||||
return nil, LayerBlockCipherOptions{}, fmt.Errorf("unsupported cipher type: %s", typ)
|
||||
}
|
||||
|
||||
// NewLayerBlockCipherHandler returns a new default handler
|
||||
func NewLayerBlockCipherHandler() (*LayerBlockCipherHandler, error) {
|
||||
h := LayerBlockCipherHandler{
|
||||
cipherMap: map[LayerCipherType]LayerBlockCipher{},
|
||||
}
|
||||
|
||||
var err error
|
||||
h.cipherMap[AES256CTR], err = NewAESCTRLayerBlockCipher(256)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to set up Cipher AES-256-CTR: %w", err)
|
||||
}
|
||||
|
||||
return &h, nil
|
||||
}
|
193
vendor/github.com/containers/ocicrypt/blockcipher/blockcipher_aes_ctr.go
generated
vendored
Normal file
193
vendor/github.com/containers/ocicrypt/blockcipher/blockcipher_aes_ctr.go
generated
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package blockcipher
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"github.com/containers/ocicrypt/utils"
|
||||
)
|
||||
|
||||
// AESCTRLayerBlockCipher implements the AES CTR stream cipher
|
||||
type AESCTRLayerBlockCipher struct {
|
||||
keylen int // in bytes
|
||||
reader io.Reader
|
||||
encrypt bool
|
||||
stream cipher.Stream
|
||||
err error
|
||||
hmac hash.Hash
|
||||
expHmac []byte
|
||||
doneEncrypting bool
|
||||
}
|
||||
|
||||
type aesctrcryptor struct {
|
||||
bc *AESCTRLayerBlockCipher
|
||||
}
|
||||
|
||||
// NewAESCTRLayerBlockCipher returns a new AES SIV block cipher of 256 or 512 bits
|
||||
func NewAESCTRLayerBlockCipher(bits int) (LayerBlockCipher, error) {
|
||||
if bits != 256 {
|
||||
return nil, errors.New("AES CTR bit count not supported")
|
||||
}
|
||||
return &AESCTRLayerBlockCipher{keylen: bits / 8}, nil
|
||||
}
|
||||
|
||||
func (r *aesctrcryptor) Read(p []byte) (int, error) {
|
||||
var (
|
||||
o int
|
||||
)
|
||||
|
||||
if r.bc.err != nil {
|
||||
return 0, r.bc.err
|
||||
}
|
||||
|
||||
o, err := utils.FillBuffer(r.bc.reader, p)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
r.bc.err = err
|
||||
} else {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
if !r.bc.encrypt {
|
||||
if _, err := r.bc.hmac.Write(p[:o]); err != nil {
|
||||
r.bc.err = fmt.Errorf("could not write to hmac: %w", err)
|
||||
return 0, r.bc.err
|
||||
}
|
||||
|
||||
if r.bc.err == io.EOF {
|
||||
// Before we return EOF we let the HMAC comparison
|
||||
// provide a verdict
|
||||
if !hmac.Equal(r.bc.hmac.Sum(nil), r.bc.expHmac) {
|
||||
r.bc.err = fmt.Errorf("could not properly decrypt byte stream; exp hmac: '%x', actual hmac: '%s'", r.bc.expHmac, r.bc.hmac.Sum(nil))
|
||||
return 0, r.bc.err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.bc.stream.XORKeyStream(p[:o], p[:o])
|
||||
|
||||
if r.bc.encrypt {
|
||||
if _, err := r.bc.hmac.Write(p[:o]); err != nil {
|
||||
r.bc.err = fmt.Errorf("could not write to hmac: %w", err)
|
||||
return 0, r.bc.err
|
||||
}
|
||||
|
||||
if r.bc.err == io.EOF {
|
||||
// Final data encrypted; Do the 'then-MAC' part
|
||||
r.bc.doneEncrypting = true
|
||||
}
|
||||
}
|
||||
|
||||
return o, r.bc.err
|
||||
}
|
||||
|
||||
// init initializes an instance
|
||||
func (bc *AESCTRLayerBlockCipher) init(encrypt bool, reader io.Reader, opts LayerBlockCipherOptions) (LayerBlockCipherOptions, error) {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
key := opts.Private.SymmetricKey
|
||||
if len(key) != bc.keylen {
|
||||
return LayerBlockCipherOptions{}, fmt.Errorf("invalid key length of %d bytes; need %d bytes", len(key), bc.keylen)
|
||||
}
|
||||
|
||||
nonce, ok := opts.GetOpt("nonce")
|
||||
if !ok {
|
||||
nonce = make([]byte, aes.BlockSize)
|
||||
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
return LayerBlockCipherOptions{}, fmt.Errorf("unable to generate random nonce: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return LayerBlockCipherOptions{}, fmt.Errorf("aes.NewCipher failed: %w", err)
|
||||
}
|
||||
|
||||
bc.reader = reader
|
||||
bc.encrypt = encrypt
|
||||
bc.stream = cipher.NewCTR(block, nonce)
|
||||
bc.err = nil
|
||||
bc.hmac = hmac.New(sha256.New, key)
|
||||
bc.expHmac = opts.Public.Hmac
|
||||
bc.doneEncrypting = false
|
||||
|
||||
if !encrypt && len(bc.expHmac) == 0 {
|
||||
return LayerBlockCipherOptions{}, errors.New("HMAC is not provided for decryption process")
|
||||
}
|
||||
|
||||
lbco := LayerBlockCipherOptions{
|
||||
Private: PrivateLayerBlockCipherOptions{
|
||||
SymmetricKey: key,
|
||||
CipherOptions: map[string][]byte{
|
||||
"nonce": nonce,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return lbco, nil
|
||||
}
|
||||
|
||||
// GenerateKey creates a synmmetric key
|
||||
func (bc *AESCTRLayerBlockCipher) GenerateKey() ([]byte, error) {
|
||||
key := make([]byte, bc.keylen)
|
||||
if _, err := io.ReadFull(rand.Reader, key); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// Encrypt takes in layer data and returns the ciphertext and relevant LayerBlockCipherOptions
|
||||
func (bc *AESCTRLayerBlockCipher) Encrypt(plainDataReader io.Reader, opt LayerBlockCipherOptions) (io.Reader, Finalizer, error) {
|
||||
lbco, err := bc.init(true, plainDataReader, opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
finalizer := func() (LayerBlockCipherOptions, error) {
|
||||
if !bc.doneEncrypting {
|
||||
return LayerBlockCipherOptions{}, errors.New("Read()ing not complete, unable to finalize")
|
||||
}
|
||||
if lbco.Public.CipherOptions == nil {
|
||||
lbco.Public.CipherOptions = map[string][]byte{}
|
||||
}
|
||||
lbco.Public.Hmac = bc.hmac.Sum(nil)
|
||||
return lbco, nil
|
||||
}
|
||||
return &aesctrcryptor{bc}, finalizer, nil
|
||||
}
|
||||
|
||||
// Decrypt takes in layer ciphertext data and returns the plaintext and relevant LayerBlockCipherOptions
|
||||
func (bc *AESCTRLayerBlockCipher) Decrypt(encDataReader io.Reader, opt LayerBlockCipherOptions) (io.Reader, LayerBlockCipherOptions, error) {
|
||||
lbco, err := bc.init(false, encDataReader, opt)
|
||||
if err != nil {
|
||||
return nil, LayerBlockCipherOptions{}, err
|
||||
}
|
||||
|
||||
return utils.NewDelayedReader(&aesctrcryptor{bc}, 1024*10), lbco, nil
|
||||
}
|
114
vendor/github.com/containers/ocicrypt/config/config.go
generated
vendored
Normal file
114
vendor/github.com/containers/ocicrypt/config/config.go
generated
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package config
|
||||
|
||||
// EncryptConfig is the container image PGP encryption configuration holding
|
||||
// the identifiers of those that will be able to decrypt the container and
|
||||
// the PGP public keyring file data that contains their public keys.
|
||||
type EncryptConfig struct {
|
||||
// map holding 'gpg-recipients', 'gpg-pubkeyringfile', 'pubkeys', 'x509s'
|
||||
Parameters map[string][][]byte
|
||||
|
||||
DecryptConfig DecryptConfig
|
||||
}
|
||||
|
||||
// DecryptConfig wraps the Parameters map that holds the decryption key
|
||||
type DecryptConfig struct {
|
||||
// map holding 'privkeys', 'x509s', 'gpg-privatekeys'
|
||||
Parameters map[string][][]byte
|
||||
}
|
||||
|
||||
// CryptoConfig is a common wrapper for EncryptConfig and DecrypConfig that can
|
||||
// be passed through functions that share much code for encryption and decryption
|
||||
type CryptoConfig struct {
|
||||
EncryptConfig *EncryptConfig
|
||||
DecryptConfig *DecryptConfig
|
||||
}
|
||||
|
||||
// InitDecryption initialized a CryptoConfig object with parameters used for decryption
|
||||
func InitDecryption(dcparameters map[string][][]byte) CryptoConfig {
|
||||
return CryptoConfig{
|
||||
DecryptConfig: &DecryptConfig{
|
||||
Parameters: dcparameters,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// InitEncryption initializes a CryptoConfig object with parameters used for encryption
|
||||
// It also takes dcparameters that may be needed for decryption when adding a recipient
|
||||
// to an already encrypted image
|
||||
func InitEncryption(parameters, dcparameters map[string][][]byte) CryptoConfig {
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: parameters,
|
||||
DecryptConfig: DecryptConfig{
|
||||
Parameters: dcparameters,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// CombineCryptoConfigs takes a CryptoConfig list and creates a single CryptoConfig
|
||||
// containing the crypto configuration of all the key bundles
|
||||
func CombineCryptoConfigs(ccs []CryptoConfig) CryptoConfig {
|
||||
ecparam := map[string][][]byte{}
|
||||
ecdcparam := map[string][][]byte{}
|
||||
dcparam := map[string][][]byte{}
|
||||
|
||||
for _, cc := range ccs {
|
||||
if ec := cc.EncryptConfig; ec != nil {
|
||||
addToMap(ecparam, ec.Parameters)
|
||||
addToMap(ecdcparam, ec.DecryptConfig.Parameters)
|
||||
}
|
||||
|
||||
if dc := cc.DecryptConfig; dc != nil {
|
||||
addToMap(dcparam, dc.Parameters)
|
||||
}
|
||||
}
|
||||
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ecparam,
|
||||
DecryptConfig: DecryptConfig{
|
||||
Parameters: ecdcparam,
|
||||
},
|
||||
},
|
||||
DecryptConfig: &DecryptConfig{
|
||||
Parameters: dcparam,
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// AttachDecryptConfig adds DecryptConfig to the field of EncryptConfig so that
|
||||
// the decryption parameters can be used to add recipients to an existing image
|
||||
// if the user is able to decrypt it.
|
||||
func (ec *EncryptConfig) AttachDecryptConfig(dc *DecryptConfig) {
|
||||
if dc != nil {
|
||||
addToMap(ec.DecryptConfig.Parameters, dc.Parameters)
|
||||
}
|
||||
}
|
||||
|
||||
func addToMap(orig map[string][][]byte, add map[string][][]byte) {
|
||||
for k, v := range add {
|
||||
if ov, ok := orig[k]; ok {
|
||||
orig[k] = append(ov, v...)
|
||||
} else {
|
||||
orig[k] = v
|
||||
}
|
||||
}
|
||||
}
|
246
vendor/github.com/containers/ocicrypt/config/constructors.go
generated
vendored
Normal file
246
vendor/github.com/containers/ocicrypt/config/constructors.go
generated
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/ocicrypt/crypto/pkcs11"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// EncryptWithJwe returns a CryptoConfig to encrypt with jwe public keys
|
||||
func EncryptWithJwe(pubKeys [][]byte) (CryptoConfig, error) {
|
||||
dc := DecryptConfig{}
|
||||
ep := map[string][][]byte{
|
||||
"pubkeys": pubKeys,
|
||||
}
|
||||
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ep,
|
||||
DecryptConfig: dc,
|
||||
},
|
||||
DecryptConfig: &dc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// EncryptWithPkcs7 returns a CryptoConfig to encrypt with pkcs7 x509 certs
|
||||
func EncryptWithPkcs7(x509s [][]byte) (CryptoConfig, error) {
|
||||
dc := DecryptConfig{}
|
||||
|
||||
ep := map[string][][]byte{
|
||||
"x509s": x509s,
|
||||
}
|
||||
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ep,
|
||||
DecryptConfig: dc,
|
||||
},
|
||||
DecryptConfig: &dc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// EncryptWithGpg returns a CryptoConfig to encrypt with configured gpg parameters
|
||||
func EncryptWithGpg(gpgRecipients [][]byte, gpgPubRingFile []byte) (CryptoConfig, error) {
|
||||
dc := DecryptConfig{}
|
||||
ep := map[string][][]byte{
|
||||
"gpg-recipients": gpgRecipients,
|
||||
"gpg-pubkeyringfile": {gpgPubRingFile},
|
||||
}
|
||||
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ep,
|
||||
DecryptConfig: dc,
|
||||
},
|
||||
DecryptConfig: &dc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// EncryptWithPkcs11 returns a CryptoConfig to encrypt with configured pkcs11 parameters
|
||||
func EncryptWithPkcs11(pkcs11Config *pkcs11.Pkcs11Config, pkcs11Pubkeys, pkcs11Yamls [][]byte) (CryptoConfig, error) {
|
||||
dc := DecryptConfig{}
|
||||
ep := map[string][][]byte{}
|
||||
|
||||
if len(pkcs11Yamls) > 0 {
|
||||
if pkcs11Config == nil {
|
||||
return CryptoConfig{}, errors.New("pkcs11Config must not be nil")
|
||||
}
|
||||
p11confYaml, err := yaml.Marshal(pkcs11Config)
|
||||
if err != nil {
|
||||
return CryptoConfig{}, fmt.Errorf("Could not marshal Pkcs11Config to Yaml: %w", err)
|
||||
}
|
||||
|
||||
dc = DecryptConfig{
|
||||
Parameters: map[string][][]byte{
|
||||
"pkcs11-config": {p11confYaml},
|
||||
},
|
||||
}
|
||||
ep["pkcs11-yamls"] = pkcs11Yamls
|
||||
}
|
||||
if len(pkcs11Pubkeys) > 0 {
|
||||
ep["pkcs11-pubkeys"] = pkcs11Pubkeys
|
||||
}
|
||||
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ep,
|
||||
DecryptConfig: dc,
|
||||
},
|
||||
DecryptConfig: &dc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// EncryptWithKeyProvider returns a CryptoConfig to encrypt with configured keyprovider parameters
|
||||
func EncryptWithKeyProvider(keyProviders [][]byte) (CryptoConfig, error) {
|
||||
dc := DecryptConfig{}
|
||||
ep := make(map[string][][]byte)
|
||||
for _, keyProvider := range keyProviders {
|
||||
keyProvidersStr := string(keyProvider)
|
||||
idx := strings.Index(keyProvidersStr, ":")
|
||||
if idx > 0 {
|
||||
ep[keyProvidersStr[:idx]] = append(ep[keyProvidersStr[:idx]], []byte(keyProvidersStr[idx+1:]))
|
||||
} else {
|
||||
ep[keyProvidersStr] = append(ep[keyProvidersStr], []byte("Enabled"))
|
||||
}
|
||||
}
|
||||
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ep,
|
||||
DecryptConfig: dc,
|
||||
},
|
||||
DecryptConfig: &dc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DecryptWithKeyProvider returns a CryptoConfig to decrypt with configured keyprovider parameters
|
||||
func DecryptWithKeyProvider(keyProviders [][]byte) (CryptoConfig, error) {
|
||||
dp := make(map[string][][]byte)
|
||||
ep := map[string][][]byte{}
|
||||
for _, keyProvider := range keyProviders {
|
||||
keyProvidersStr := string(keyProvider)
|
||||
idx := strings.Index(keyProvidersStr, ":")
|
||||
if idx > 0 {
|
||||
dp[keyProvidersStr[:idx]] = append(dp[keyProvidersStr[:idx]], []byte(keyProvidersStr[idx+1:]))
|
||||
} else {
|
||||
dp[keyProvidersStr] = append(dp[keyProvidersStr], []byte("Enabled"))
|
||||
}
|
||||
}
|
||||
dc := DecryptConfig{
|
||||
Parameters: dp,
|
||||
}
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ep,
|
||||
DecryptConfig: dc,
|
||||
},
|
||||
DecryptConfig: &dc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DecryptWithPrivKeys returns a CryptoConfig to decrypt with configured private keys
|
||||
func DecryptWithPrivKeys(privKeys [][]byte, privKeysPasswords [][]byte) (CryptoConfig, error) {
|
||||
if len(privKeys) != len(privKeysPasswords) {
|
||||
return CryptoConfig{}, errors.New("Length of privKeys should match length of privKeysPasswords")
|
||||
}
|
||||
|
||||
dc := DecryptConfig{
|
||||
Parameters: map[string][][]byte{
|
||||
"privkeys": privKeys,
|
||||
"privkeys-passwords": privKeysPasswords,
|
||||
},
|
||||
}
|
||||
|
||||
ep := map[string][][]byte{}
|
||||
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ep,
|
||||
DecryptConfig: dc,
|
||||
},
|
||||
DecryptConfig: &dc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DecryptWithX509s returns a CryptoConfig to decrypt with configured x509 certs
|
||||
func DecryptWithX509s(x509s [][]byte) (CryptoConfig, error) {
|
||||
dc := DecryptConfig{
|
||||
Parameters: map[string][][]byte{
|
||||
"x509s": x509s,
|
||||
},
|
||||
}
|
||||
|
||||
ep := map[string][][]byte{}
|
||||
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ep,
|
||||
DecryptConfig: dc,
|
||||
},
|
||||
DecryptConfig: &dc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DecryptWithGpgPrivKeys returns a CryptoConfig to decrypt with configured gpg private keys
|
||||
func DecryptWithGpgPrivKeys(gpgPrivKeys, gpgPrivKeysPwds [][]byte) (CryptoConfig, error) {
|
||||
dc := DecryptConfig{
|
||||
Parameters: map[string][][]byte{
|
||||
"gpg-privatekeys": gpgPrivKeys,
|
||||
"gpg-privatekeys-passwords": gpgPrivKeysPwds,
|
||||
},
|
||||
}
|
||||
|
||||
ep := map[string][][]byte{}
|
||||
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ep,
|
||||
DecryptConfig: dc,
|
||||
},
|
||||
DecryptConfig: &dc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DecryptWithPkcs11Yaml returns a CryptoConfig to decrypt with pkcs11 YAML formatted key files
|
||||
func DecryptWithPkcs11Yaml(pkcs11Config *pkcs11.Pkcs11Config, pkcs11Yamls [][]byte) (CryptoConfig, error) {
|
||||
p11confYaml, err := yaml.Marshal(pkcs11Config)
|
||||
if err != nil {
|
||||
return CryptoConfig{}, fmt.Errorf("Could not marshal Pkcs11Config to Yaml: %w", err)
|
||||
}
|
||||
|
||||
dc := DecryptConfig{
|
||||
Parameters: map[string][][]byte{
|
||||
"pkcs11-yamls": pkcs11Yamls,
|
||||
"pkcs11-config": {p11confYaml},
|
||||
},
|
||||
}
|
||||
|
||||
ep := map[string][][]byte{}
|
||||
|
||||
return CryptoConfig{
|
||||
EncryptConfig: &EncryptConfig{
|
||||
Parameters: ep,
|
||||
DecryptConfig: dc,
|
||||
},
|
||||
DecryptConfig: &dc,
|
||||
}, nil
|
||||
}
|
80
vendor/github.com/containers/ocicrypt/config/keyprovider-config/config.go
generated
vendored
Normal file
80
vendor/github.com/containers/ocicrypt/config/keyprovider-config/config.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Command describes the structure of command, it consist of path and args, where path defines the location of
|
||||
// binary executable and args are passed on to the binary executable
|
||||
type Command struct {
|
||||
Path string `json:"path,omitempty"`
|
||||
Args []string `json:"args,omitempty"`
|
||||
}
|
||||
|
||||
// KeyProviderAttrs describes the structure of key provider, it defines the way of invocation to key provider
|
||||
type KeyProviderAttrs struct {
|
||||
Command *Command `json:"cmd,omitempty"`
|
||||
Grpc string `json:"grpc,omitempty"`
|
||||
}
|
||||
|
||||
// OcicryptConfig represents the format of an ocicrypt_provider.conf config file
|
||||
type OcicryptConfig struct {
|
||||
KeyProviderConfig map[string]KeyProviderAttrs `json:"key-providers"`
|
||||
}
|
||||
|
||||
const ENVVARNAME = "OCICRYPT_KEYPROVIDER_CONFIG"
|
||||
|
||||
// parseConfigFile parses a configuration file; it is not an error if the configuration file does
|
||||
// not exist, so no error is returned.
|
||||
func parseConfigFile(filename string) (*OcicryptConfig, error) {
|
||||
// a non-existent config file is not an error
|
||||
_, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ic := &OcicryptConfig{}
|
||||
err = json.Unmarshal(data, ic)
|
||||
return ic, err
|
||||
}
|
||||
|
||||
// getConfiguration tries to read the configuration file at the following locations
|
||||
// ${OCICRYPT_KEYPROVIDER_CONFIG} == "/etc/ocicrypt_keyprovider.yaml"
|
||||
// If no configuration file could be found or read a null pointer is returned
|
||||
func GetConfiguration() (*OcicryptConfig, error) {
|
||||
var ic *OcicryptConfig
|
||||
var err error
|
||||
filename := os.Getenv(ENVVARNAME)
|
||||
if len(filename) > 0 {
|
||||
ic, err = parseConfigFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error while parsing keyprovider config file: %w", err)
|
||||
}
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
return ic, nil
|
||||
}
|
134
vendor/github.com/containers/ocicrypt/crypto/pkcs11/common.go
generated
vendored
Normal file
134
vendor/github.com/containers/ocicrypt/crypto/pkcs11/common.go
generated
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pkcs11
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
pkcs11uri "github.com/stefanberger/go-pkcs11uri"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Pkcs11KeyFile describes the format of the pkcs11 (private) key file.
|
||||
// It also carries pkcs11 module related environment variables that are transferred to the
|
||||
// Pkcs11URI object and activated when the pkcs11 module is used.
|
||||
type Pkcs11KeyFile struct {
|
||||
Pkcs11 struct {
|
||||
Uri string `yaml:"uri"`
|
||||
} `yaml:"pkcs11"`
|
||||
Module struct {
|
||||
Env map[string]string `yaml:"env,omitempty"`
|
||||
} `yaml:"module"`
|
||||
}
|
||||
|
||||
// Pkcs11KeyFileObject is a representation of the Pkcs11KeyFile with the pkcs11 URI as an object
|
||||
type Pkcs11KeyFileObject struct {
|
||||
Uri *pkcs11uri.Pkcs11URI
|
||||
}
|
||||
|
||||
// ParsePkcs11Uri parses a pkcs11 URI
|
||||
func ParsePkcs11Uri(uri string) (*pkcs11uri.Pkcs11URI, error) {
|
||||
p11uri := pkcs11uri.New()
|
||||
err := p11uri.Parse(uri)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not parse Pkcs11URI from file: %w", err)
|
||||
}
|
||||
return p11uri, err
|
||||
}
|
||||
|
||||
// ParsePkcs11KeyFile parses a pkcs11 key file holding a pkcs11 URI describing a private key.
|
||||
// The file has the following yaml format:
|
||||
// pkcs11:
|
||||
// - uri : <pkcs11 uri>
|
||||
// An error is returned if the pkcs11 URI is malformed
|
||||
func ParsePkcs11KeyFile(yamlstr []byte) (*Pkcs11KeyFileObject, error) {
|
||||
p11keyfile := Pkcs11KeyFile{}
|
||||
|
||||
err := yaml.Unmarshal(yamlstr, &p11keyfile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not unmarshal pkcs11 keyfile: %w", err)
|
||||
}
|
||||
|
||||
p11uri, err := ParsePkcs11Uri(p11keyfile.Pkcs11.Uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p11uri.SetEnvMap(p11keyfile.Module.Env)
|
||||
|
||||
return &Pkcs11KeyFileObject{Uri: p11uri}, err
|
||||
}
|
||||
|
||||
// IsPkcs11PrivateKey checks whether the given YAML represents a Pkcs11 private key
|
||||
func IsPkcs11PrivateKey(yamlstr []byte) bool {
|
||||
_, err := ParsePkcs11KeyFile(yamlstr)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsPkcs11PublicKey checks whether the given YAML represents a Pkcs11 public key
|
||||
func IsPkcs11PublicKey(yamlstr []byte) bool {
|
||||
_, err := ParsePkcs11KeyFile(yamlstr)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Pkcs11Config describes the layout of a pkcs11 config file
|
||||
// The file has the following yaml format:
|
||||
// module-directories:
|
||||
// - /usr/lib64/pkcs11/
|
||||
// allowd-module-paths
|
||||
// - /usr/lib64/pkcs11/libsofthsm2.so
|
||||
type Pkcs11Config struct {
|
||||
ModuleDirectories []string `yaml:"module-directories"`
|
||||
AllowedModulePaths []string `yaml:"allowed-module-paths"`
|
||||
}
|
||||
|
||||
// GetDefaultModuleDirectories returns module directories covering
|
||||
// a variety of Linux distros
|
||||
func GetDefaultModuleDirectories() []string {
|
||||
dirs := []string{
|
||||
"/usr/lib64/pkcs11/", // Fedora,RHEL,openSUSE
|
||||
"/usr/lib/pkcs11/", // Fedora,ArchLinux
|
||||
"/usr/local/lib/pkcs11/",
|
||||
"/usr/lib/softhsm/", // Debian,Ubuntu
|
||||
}
|
||||
|
||||
// Debian directory: /usr/lib/(x86_64|aarch64|arm|powerpc64le|riscv64|s390x)-linux-gnu/
|
||||
hosttype, ostype, q := getHostAndOsType()
|
||||
if len(hosttype) > 0 {
|
||||
dir := fmt.Sprintf("/usr/lib/%s-%s-%s/", hosttype, ostype, q)
|
||||
dirs = append(dirs, dir)
|
||||
}
|
||||
return dirs
|
||||
}
|
||||
|
||||
// GetDefaultModuleDirectoresFormatted returns the default module directories formatted for YAML
|
||||
func GetDefaultModuleDirectoriesYaml(indent string) string {
|
||||
res := ""
|
||||
|
||||
for _, dir := range GetDefaultModuleDirectories() {
|
||||
res += indent + "- " + dir + "\n"
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ParsePkcs11ConfigFile parses a pkcs11 config file hat influences the module search behavior
|
||||
// as well as the set of modules that users are allowed to use
|
||||
func ParsePkcs11ConfigFile(yamlstr []byte) (*Pkcs11Config, error) {
|
||||
p11conf := Pkcs11Config{}
|
||||
|
||||
err := yaml.Unmarshal(yamlstr, &p11conf)
|
||||
if err != nil {
|
||||
return &p11conf, fmt.Errorf("Could not parse Pkcs11Config: %w", err)
|
||||
}
|
||||
return &p11conf, nil
|
||||
}
|
485
vendor/github.com/containers/ocicrypt/crypto/pkcs11/pkcs11helpers.go
generated
vendored
Normal file
485
vendor/github.com/containers/ocicrypt/crypto/pkcs11/pkcs11helpers.go
generated
vendored
Normal file
@ -0,0 +1,485 @@
|
||||
//go:build cgo
|
||||
// +build cgo
|
||||
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pkcs11
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/miekg/pkcs11"
|
||||
pkcs11uri "github.com/stefanberger/go-pkcs11uri"
|
||||
)
|
||||
|
||||
var (
|
||||
// OAEPLabel defines the label we use for OAEP encryption; this cannot be changed
|
||||
OAEPLabel = []byte("")
|
||||
|
||||
// OAEPSha1Params describes the OAEP parameters with sha1 hash algorithm; needed by SoftHSM
|
||||
OAEPSha1Params = &pkcs11.OAEPParams{
|
||||
HashAlg: pkcs11.CKM_SHA_1,
|
||||
MGF: pkcs11.CKG_MGF1_SHA1,
|
||||
SourceType: pkcs11.CKZ_DATA_SPECIFIED,
|
||||
SourceData: OAEPLabel,
|
||||
}
|
||||
// OAEPSha256Params describes the OAEP parameters with sha256 hash algorithm
|
||||
OAEPSha256Params = &pkcs11.OAEPParams{
|
||||
HashAlg: pkcs11.CKM_SHA256,
|
||||
MGF: pkcs11.CKG_MGF1_SHA256,
|
||||
SourceType: pkcs11.CKZ_DATA_SPECIFIED,
|
||||
SourceData: OAEPLabel,
|
||||
}
|
||||
)
|
||||
|
||||
// rsaPublicEncryptOAEP encrypts the given plaintext with the given *rsa.PublicKey; the
|
||||
// environment variable OCICRYPT_OAEP_HASHALG can be set to 'sha1' to force usage of sha1 for OAEP (SoftHSM).
|
||||
// This function is needed by clients who are using a public key file for pkcs11 encryption
|
||||
func rsaPublicEncryptOAEP(pubKey *rsa.PublicKey, plaintext []byte) ([]byte, string, error) {
|
||||
var (
|
||||
hashfunc hash.Hash
|
||||
hashalg string
|
||||
)
|
||||
|
||||
oaephash := os.Getenv("OCICRYPT_OAEP_HASHALG")
|
||||
// The default is sha256 (previously was sha1)
|
||||
switch strings.ToLower(oaephash) {
|
||||
case "sha1":
|
||||
hashfunc = sha1.New()
|
||||
hashalg = "sha1"
|
||||
case "sha256", "":
|
||||
hashfunc = sha256.New()
|
||||
hashalg = "sha256"
|
||||
default:
|
||||
return nil, "", fmt.Errorf("Unsupported OAEP hash '%s'", oaephash)
|
||||
}
|
||||
ciphertext, err := rsa.EncryptOAEP(hashfunc, rand.Reader, pubKey, plaintext, OAEPLabel)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("rss.EncryptOAEP failed: %w", err)
|
||||
}
|
||||
|
||||
return ciphertext, hashalg, nil
|
||||
}
|
||||
|
||||
// pkcs11UriGetLoginParameters gets the parameters necessary for login from the Pkcs11URI
|
||||
// PIN and module are mandatory; slot-id is optional and if not found -1 will be returned
|
||||
// For a privateKeyOperation a PIN is required and if none is given, this function will return an error
|
||||
func pkcs11UriGetLoginParameters(p11uri *pkcs11uri.Pkcs11URI, privateKeyOperation bool) (string, string, int64, error) {
|
||||
var (
|
||||
pin string
|
||||
err error
|
||||
)
|
||||
if privateKeyOperation {
|
||||
if !p11uri.HasPIN() {
|
||||
return "", "", 0, errors.New("Missing PIN for private key operation")
|
||||
}
|
||||
}
|
||||
// some devices require a PIN to find a *public* key object, others don't
|
||||
pin, _ = p11uri.GetPIN()
|
||||
|
||||
module, err := p11uri.GetModule()
|
||||
if err != nil {
|
||||
return "", "", 0, fmt.Errorf("No module available in pkcs11 URI: %w", err)
|
||||
}
|
||||
|
||||
slotid := int64(-1)
|
||||
|
||||
slot, ok := p11uri.GetPathAttribute("slot-id", false)
|
||||
if ok {
|
||||
slotid, err = strconv.ParseInt(slot, 10, 64)
|
||||
if err != nil {
|
||||
return "", "", 0, fmt.Errorf("slot-id is not a valid number: %w", err)
|
||||
}
|
||||
if slotid < 0 {
|
||||
return "", "", 0, fmt.Errorf("slot-id is a negative number")
|
||||
}
|
||||
if uint64(slotid) > 0xffffffff {
|
||||
return "", "", 0, fmt.Errorf("slot-id is larger than 32 bit")
|
||||
}
|
||||
}
|
||||
|
||||
return pin, module, slotid, nil
|
||||
}
|
||||
|
||||
// pkcs11UriGetKeyIdAndLabel gets the key label by retrieving the value of the 'object' attribute
|
||||
func pkcs11UriGetKeyIdAndLabel(p11uri *pkcs11uri.Pkcs11URI) (string, string, error) {
|
||||
keyid, ok2 := p11uri.GetPathAttribute("id", false)
|
||||
label, ok1 := p11uri.GetPathAttribute("object", false)
|
||||
if !ok1 && !ok2 {
|
||||
return "", "", errors.New("Neither 'id' nor 'object' attributes were found in pkcs11 URI")
|
||||
}
|
||||
return keyid, label, nil
|
||||
}
|
||||
|
||||
// pkcs11OpenSession opens a session with a pkcs11 device at the given slot and logs in with the given PIN
|
||||
func pkcs11OpenSession(p11ctx *pkcs11.Ctx, slotid uint, pin string) (session pkcs11.SessionHandle, err error) {
|
||||
session, err = p11ctx.OpenSession(slotid, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("OpenSession to slot %d failed: %w", slotid, err)
|
||||
}
|
||||
if len(pin) > 0 {
|
||||
err = p11ctx.Login(session, pkcs11.CKU_USER, pin)
|
||||
if err != nil {
|
||||
_ = p11ctx.CloseSession(session)
|
||||
return 0, fmt.Errorf("Could not login to device: %w", err)
|
||||
}
|
||||
}
|
||||
return session, nil
|
||||
}
|
||||
|
||||
// pkcs11UriLogin uses the given pkcs11 URI to select the pkcs11 module (shared library) and to get
|
||||
// the PIN to use for login; if the URI contains a slot-id, the given slot-id will be used, otherwise
|
||||
// one slot after the other will be attempted and the first one where login succeeds will be used
|
||||
func pkcs11UriLogin(p11uri *pkcs11uri.Pkcs11URI, privateKeyOperation bool) (ctx *pkcs11.Ctx, session pkcs11.SessionHandle, err error) {
|
||||
pin, module, slotid, err := pkcs11UriGetLoginParameters(p11uri, privateKeyOperation)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
p11ctx := pkcs11.New(module)
|
||||
if p11ctx == nil {
|
||||
return nil, 0, errors.New("Please check module path, input is: " + module)
|
||||
}
|
||||
|
||||
err = p11ctx.Initialize()
|
||||
if err != nil {
|
||||
p11Err := err.(pkcs11.Error)
|
||||
if p11Err != pkcs11.CKR_CRYPTOKI_ALREADY_INITIALIZED {
|
||||
return nil, 0, fmt.Errorf("Initialize failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if slotid >= 0 {
|
||||
session, err := pkcs11OpenSession(p11ctx, uint(slotid), pin)
|
||||
return p11ctx, session, err
|
||||
}
|
||||
|
||||
slots, err := p11ctx.GetSlotList(true)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("GetSlotList failed: %w", err)
|
||||
}
|
||||
|
||||
tokenlabel, ok := p11uri.GetPathAttribute("token", false)
|
||||
if !ok {
|
||||
return nil, 0, errors.New("Missing 'token' attribute since 'slot-id' was not given")
|
||||
}
|
||||
|
||||
for _, slot := range slots {
|
||||
ti, err := p11ctx.GetTokenInfo(slot)
|
||||
if err != nil || ti.Label != tokenlabel {
|
||||
continue
|
||||
}
|
||||
|
||||
session, err = pkcs11OpenSession(p11ctx, slot, pin)
|
||||
if err == nil {
|
||||
return p11ctx, session, err
|
||||
}
|
||||
}
|
||||
if len(pin) > 0 {
|
||||
return nil, 0, errors.New("Could not create session to any slot and/or log in")
|
||||
}
|
||||
return nil, 0, errors.New("Could not create session to any slot")
|
||||
}
|
||||
|
||||
func pkcs11Logout(ctx *pkcs11.Ctx, session pkcs11.SessionHandle) {
|
||||
_ = ctx.Logout(session)
|
||||
_ = ctx.CloseSession(session)
|
||||
_ = ctx.Finalize()
|
||||
ctx.Destroy()
|
||||
}
|
||||
|
||||
// findObject finds an object of the given class with the given keyid and/or label
|
||||
func findObject(p11ctx *pkcs11.Ctx, session pkcs11.SessionHandle, class uint, keyid, label string) (pkcs11.ObjectHandle, error) {
|
||||
msg := ""
|
||||
|
||||
template := []*pkcs11.Attribute{
|
||||
pkcs11.NewAttribute(pkcs11.CKA_CLASS, class),
|
||||
}
|
||||
if len(label) > 0 {
|
||||
template = append(template, pkcs11.NewAttribute(pkcs11.CKA_LABEL, label))
|
||||
msg = fmt.Sprintf("label '%s'", label)
|
||||
}
|
||||
if len(keyid) > 0 {
|
||||
template = append(template, pkcs11.NewAttribute(pkcs11.CKA_ID, keyid))
|
||||
if len(msg) > 0 {
|
||||
msg += " and "
|
||||
}
|
||||
msg += url.PathEscape(keyid)
|
||||
}
|
||||
|
||||
if err := p11ctx.FindObjectsInit(session, template); err != nil {
|
||||
return 0, fmt.Errorf("FindObjectsInit failed: %w", err)
|
||||
}
|
||||
|
||||
obj, _, err := p11ctx.FindObjects(session, 100)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("FindObjects failed: %w", err)
|
||||
}
|
||||
|
||||
if err := p11ctx.FindObjectsFinal(session); err != nil {
|
||||
return 0, fmt.Errorf("FindObjectsFinal failed: %w", err)
|
||||
}
|
||||
if len(obj) > 1 {
|
||||
return 0, fmt.Errorf("There are too many (=%d) keys with %s", len(obj), msg)
|
||||
} else if len(obj) == 1 {
|
||||
return obj[0], nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("Could not find any object with %s", msg)
|
||||
}
|
||||
|
||||
// publicEncryptOAEP uses a public key described by a pkcs11 URI to OAEP encrypt the given plaintext
|
||||
func publicEncryptOAEP(pubKey *Pkcs11KeyFileObject, plaintext []byte) ([]byte, string, error) {
|
||||
oldenv, err := setEnvVars(pubKey.Uri.GetEnvMap())
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
defer restoreEnv(oldenv)
|
||||
|
||||
p11ctx, session, err := pkcs11UriLogin(pubKey.Uri, false)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
defer pkcs11Logout(p11ctx, session)
|
||||
|
||||
keyid, label, err := pkcs11UriGetKeyIdAndLabel(pubKey.Uri)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
p11PubKey, err := findObject(p11ctx, session, pkcs11.CKO_PUBLIC_KEY, keyid, label)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
var hashalg string
|
||||
|
||||
var oaep *pkcs11.OAEPParams
|
||||
oaephash := os.Getenv("OCICRYPT_OAEP_HASHALG")
|
||||
// The default is sha256 (previously was sha1)
|
||||
switch strings.ToLower(oaephash) {
|
||||
case "sha1":
|
||||
oaep = OAEPSha1Params
|
||||
hashalg = "sha1"
|
||||
case "sha256", "":
|
||||
oaep = OAEPSha256Params
|
||||
hashalg = "sha256"
|
||||
default:
|
||||
return nil, "", fmt.Errorf("Unsupported OAEP hash '%s'", oaephash)
|
||||
}
|
||||
|
||||
err = p11ctx.EncryptInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_OAEP, oaep)}, p11PubKey)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("EncryptInit error: %w", err)
|
||||
}
|
||||
|
||||
ciphertext, err := p11ctx.Encrypt(session, plaintext)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("Encrypt failed: %w", err)
|
||||
}
|
||||
return ciphertext, hashalg, nil
|
||||
}
|
||||
|
||||
// privateDecryptOAEP uses a pkcs11 URI describing a private key to OAEP decrypt a ciphertext
|
||||
func privateDecryptOAEP(privKeyObj *Pkcs11KeyFileObject, ciphertext []byte, hashalg string) ([]byte, error) {
|
||||
oldenv, err := setEnvVars(privKeyObj.Uri.GetEnvMap())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer restoreEnv(oldenv)
|
||||
|
||||
p11ctx, session, err := pkcs11UriLogin(privKeyObj.Uri, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer pkcs11Logout(p11ctx, session)
|
||||
|
||||
keyid, label, err := pkcs11UriGetKeyIdAndLabel(privKeyObj.Uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p11PrivKey, err := findObject(p11ctx, session, pkcs11.CKO_PRIVATE_KEY, keyid, label)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var oaep *pkcs11.OAEPParams
|
||||
|
||||
// An empty string from the Hash in the JSON historically defaults to sha1.
|
||||
switch hashalg {
|
||||
case "sha1", "":
|
||||
oaep = OAEPSha1Params
|
||||
case "sha256":
|
||||
oaep = OAEPSha256Params
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupported hash algorithm '%s' for decryption", hashalg)
|
||||
}
|
||||
|
||||
err = p11ctx.DecryptInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_OAEP, oaep)}, p11PrivKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("DecryptInit failed: %w", err)
|
||||
}
|
||||
plaintext, err := p11ctx.Decrypt(session, ciphertext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Decrypt failed: %w", err)
|
||||
}
|
||||
return plaintext, err
|
||||
}
|
||||
|
||||
//
|
||||
// The following part deals with the JSON formatted message for multiple pkcs11 recipients
|
||||
//
|
||||
|
||||
// Pkcs11Blob holds the encrypted blobs for all recipients; this is what we will put into the image's annotations
|
||||
type Pkcs11Blob struct {
|
||||
Version uint `json:"version"`
|
||||
Recipients []Pkcs11Recipient `json:"recipients"`
|
||||
}
|
||||
|
||||
// Pkcs11Recipient holds the b64-encoded and encrypted blob for a particular recipient
|
||||
type Pkcs11Recipient struct {
|
||||
Version uint `json:"version"`
|
||||
Blob string `json:"blob"`
|
||||
Hash string `json:"hash,omitempty"`
|
||||
}
|
||||
|
||||
// EncryptMultiple encrypts for one or multiple pkcs11 devices; the public keys passed to this function
|
||||
// may either be *rsa.PublicKey or *pkcs11uri.Pkcs11URI; the returned byte array is a JSON string of the
|
||||
// following format:
|
||||
// {
|
||||
// recipients: [ // recipient list
|
||||
// {
|
||||
// "version": 0,
|
||||
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
||||
// "hash": <hash used for OAEP other than 'sha256'>
|
||||
// } ,
|
||||
// {
|
||||
// "version": 0,
|
||||
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
||||
// "hash": <hash used for OAEP other than 'sha256'>
|
||||
// } ,
|
||||
// [...]
|
||||
// ]
|
||||
// }
|
||||
func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
|
||||
var (
|
||||
ciphertext []byte
|
||||
err error
|
||||
pkcs11blob Pkcs11Blob = Pkcs11Blob{Version: 0}
|
||||
hashalg string
|
||||
)
|
||||
|
||||
for _, pubKey := range pubKeys {
|
||||
switch pkey := pubKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
ciphertext, hashalg, err = rsaPublicEncryptOAEP(pkey, data)
|
||||
case *Pkcs11KeyFileObject:
|
||||
ciphertext, hashalg, err = publicEncryptOAEP(pkey, data)
|
||||
default:
|
||||
err = fmt.Errorf("Unsupported key object type for pkcs11 public key")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
recipient := Pkcs11Recipient{
|
||||
Version: 0,
|
||||
Blob: base64.StdEncoding.EncodeToString(ciphertext),
|
||||
Hash: hashalg,
|
||||
}
|
||||
|
||||
pkcs11blob.Recipients = append(pkcs11blob.Recipients, recipient)
|
||||
}
|
||||
return json.Marshal(&pkcs11blob)
|
||||
}
|
||||
|
||||
// Decrypt tries to decrypt one of the recipients' blobs using a pkcs11 private key.
|
||||
// The input pkcs11blobstr is a string with the following format:
|
||||
// {
|
||||
// recipients: [ // recipient list
|
||||
// {
|
||||
// "version": 0,
|
||||
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
||||
// "hash": <hash used for OAEP other than 'sha1'>
|
||||
// } ,
|
||||
// {
|
||||
// "version": 0,
|
||||
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
||||
// "hash": <hash used for OAEP other than 'sha1'>
|
||||
// } ,
|
||||
// [...]
|
||||
// }
|
||||
// Note: More recent versions of this code explicitly write 'sha1'
|
||||
// while older versions left it empty in case of 'sha1'.
|
||||
func Decrypt(privKeyObjs []*Pkcs11KeyFileObject, pkcs11blobstr []byte) ([]byte, error) {
|
||||
pkcs11blob := Pkcs11Blob{}
|
||||
err := json.Unmarshal(pkcs11blobstr, &pkcs11blob)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not parse Pkcs11Blob: %w", err)
|
||||
}
|
||||
switch pkcs11blob.Version {
|
||||
case 0:
|
||||
// latest supported version
|
||||
default:
|
||||
return nil, fmt.Errorf("found Pkcs11Blob with version %d but maximum supported version is 0", pkcs11blob.Version)
|
||||
}
|
||||
// since we do trial and error, collect all encountered errors
|
||||
errs := ""
|
||||
|
||||
for _, recipient := range pkcs11blob.Recipients {
|
||||
switch recipient.Version {
|
||||
case 0:
|
||||
// last supported version
|
||||
default:
|
||||
return nil, fmt.Errorf("found Pkcs11Recipient with version %d but maximum supported version is 0", recipient.Version)
|
||||
}
|
||||
|
||||
ciphertext, err := base64.StdEncoding.DecodeString(recipient.Blob)
|
||||
if err != nil || len(ciphertext) == 0 {
|
||||
// This should never happen... we skip over decoding issues
|
||||
errs += fmt.Sprintf("Base64 decoding failed: %s\n", err)
|
||||
continue
|
||||
}
|
||||
// try all keys until one works
|
||||
for _, privKeyObj := range privKeyObjs {
|
||||
plaintext, err := privateDecryptOAEP(privKeyObj, ciphertext, recipient.Hash)
|
||||
if err == nil {
|
||||
return plaintext, nil
|
||||
}
|
||||
if uri, err2 := privKeyObj.Uri.Format(); err2 == nil {
|
||||
errs += fmt.Sprintf("%s : %s\n", uri, err)
|
||||
} else {
|
||||
errs += fmt.Sprintf("%s\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Could not find a pkcs11 key for decryption:\n%s", errs)
|
||||
}
|
30
vendor/github.com/containers/ocicrypt/crypto/pkcs11/pkcs11helpers_nocgo.go
generated
vendored
Normal file
30
vendor/github.com/containers/ocicrypt/crypto/pkcs11/pkcs11helpers_nocgo.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
//go:build !cgo
|
||||
// +build !cgo
|
||||
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pkcs11
|
||||
|
||||
import "fmt"
|
||||
|
||||
func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
|
||||
return nil, fmt.Errorf("ocicrypt pkcs11 not supported on this build")
|
||||
}
|
||||
|
||||
func Decrypt(privKeyObjs []*Pkcs11KeyFileObject, pkcs11blobstr []byte) ([]byte, error) {
|
||||
return nil, fmt.Errorf("ocicrypt pkcs11 not supported on this build")
|
||||
}
|
115
vendor/github.com/containers/ocicrypt/crypto/pkcs11/utils.go
generated
vendored
Normal file
115
vendor/github.com/containers/ocicrypt/crypto/pkcs11/utils.go
generated
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pkcs11
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
envLock sync.Mutex
|
||||
)
|
||||
|
||||
// setEnvVars sets the environment variables given in the map and locks the environment from
|
||||
// modification with the same function; if successful, you *must* call restoreEnv with the return
|
||||
// value from this function
|
||||
func setEnvVars(env map[string]string) ([]string, error) {
|
||||
envLock.Lock()
|
||||
|
||||
if len(env) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
oldenv := os.Environ()
|
||||
|
||||
for k, v := range env {
|
||||
err := os.Setenv(k, v)
|
||||
if err != nil {
|
||||
restoreEnv(oldenv)
|
||||
return nil, fmt.Errorf("Could not set environment variable '%s' to '%s': %w", k, v, err)
|
||||
}
|
||||
}
|
||||
|
||||
return oldenv, nil
|
||||
}
|
||||
|
||||
func arrayToMap(elements []string) map[string]string {
|
||||
o := make(map[string]string)
|
||||
|
||||
for _, element := range elements {
|
||||
p := strings.SplitN(element, "=", 2)
|
||||
if len(p) == 2 {
|
||||
o[p[0]] = p[1]
|
||||
}
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
// restoreEnv restores the environment to be exactly as given in the array of strings
|
||||
// and unlocks the lock
|
||||
func restoreEnv(envs []string) {
|
||||
if envs != nil && len(envs) >= 0 {
|
||||
target := arrayToMap(envs)
|
||||
curr := arrayToMap(os.Environ())
|
||||
|
||||
for nc, vc := range curr {
|
||||
vt, ok := target[nc]
|
||||
if !ok {
|
||||
os.Unsetenv(nc)
|
||||
} else if vc == vt {
|
||||
delete(target, nc)
|
||||
}
|
||||
}
|
||||
|
||||
for nt, vt := range target {
|
||||
os.Setenv(nt, vt)
|
||||
}
|
||||
}
|
||||
|
||||
envLock.Unlock()
|
||||
}
|
||||
|
||||
func getHostAndOsType() (string, string, string) {
|
||||
ht := ""
|
||||
ot := ""
|
||||
st := ""
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
ot = "linux"
|
||||
st = "gnu"
|
||||
switch runtime.GOARCH {
|
||||
case "arm":
|
||||
ht = "arm"
|
||||
case "arm64":
|
||||
ht = "aarch64"
|
||||
case "amd64":
|
||||
ht = "x86_64"
|
||||
case "ppc64le":
|
||||
ht = "powerpc64le"
|
||||
case "riscv64":
|
||||
ht = "riscv64"
|
||||
case "s390x":
|
||||
ht = "s390x"
|
||||
}
|
||||
}
|
||||
return ht, ot, st
|
||||
}
|
356
vendor/github.com/containers/ocicrypt/encryption.go
generated
vendored
Normal file
356
vendor/github.com/containers/ocicrypt/encryption.go
generated
vendored
Normal file
@ -0,0 +1,356 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ocicrypt
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/ocicrypt/blockcipher"
|
||||
"github.com/containers/ocicrypt/config"
|
||||
keyproviderconfig "github.com/containers/ocicrypt/config/keyprovider-config"
|
||||
"github.com/containers/ocicrypt/keywrap"
|
||||
"github.com/containers/ocicrypt/keywrap/jwe"
|
||||
"github.com/containers/ocicrypt/keywrap/keyprovider"
|
||||
"github.com/containers/ocicrypt/keywrap/pgp"
|
||||
"github.com/containers/ocicrypt/keywrap/pkcs11"
|
||||
"github.com/containers/ocicrypt/keywrap/pkcs7"
|
||||
"github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// EncryptLayerFinalizer is a finalizer run to return the annotations to set for
|
||||
// the encrypted layer
|
||||
type EncryptLayerFinalizer func() (map[string]string, error)
|
||||
|
||||
func init() {
|
||||
keyWrappers = make(map[string]keywrap.KeyWrapper)
|
||||
keyWrapperAnnotations = make(map[string]string)
|
||||
RegisterKeyWrapper("pgp", pgp.NewKeyWrapper())
|
||||
RegisterKeyWrapper("jwe", jwe.NewKeyWrapper())
|
||||
RegisterKeyWrapper("pkcs7", pkcs7.NewKeyWrapper())
|
||||
RegisterKeyWrapper("pkcs11", pkcs11.NewKeyWrapper())
|
||||
ic, err := keyproviderconfig.GetConfiguration()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
} else if ic != nil {
|
||||
for provider, attrs := range ic.KeyProviderConfig {
|
||||
RegisterKeyWrapper("provider."+provider, keyprovider.NewKeyWrapper(provider, attrs))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var keyWrappers map[string]keywrap.KeyWrapper
|
||||
var keyWrapperAnnotations map[string]string
|
||||
|
||||
// RegisterKeyWrapper allows to register key wrappers by their encryption scheme
|
||||
func RegisterKeyWrapper(scheme string, iface keywrap.KeyWrapper) {
|
||||
keyWrappers[scheme] = iface
|
||||
keyWrapperAnnotations[iface.GetAnnotationID()] = scheme
|
||||
}
|
||||
|
||||
// GetKeyWrapper looks up the encryptor interface given an encryption scheme (gpg, jwe)
|
||||
func GetKeyWrapper(scheme string) keywrap.KeyWrapper {
|
||||
return keyWrappers[scheme]
|
||||
}
|
||||
|
||||
// GetWrappedKeysMap returns a map of wrappedKeys as values in a
|
||||
// map with the encryption scheme(s) as the key(s)
|
||||
func GetWrappedKeysMap(desc ocispec.Descriptor) map[string]string {
|
||||
wrappedKeysMap := make(map[string]string)
|
||||
|
||||
for annotationsID, scheme := range keyWrapperAnnotations {
|
||||
if annotation, ok := desc.Annotations[annotationsID]; ok {
|
||||
wrappedKeysMap[scheme] = annotation
|
||||
}
|
||||
}
|
||||
return wrappedKeysMap
|
||||
}
|
||||
|
||||
// EncryptLayer encrypts the layer by running one encryptor after the other
|
||||
func EncryptLayer(ec *config.EncryptConfig, encOrPlainLayerReader io.Reader, desc ocispec.Descriptor) (io.Reader, EncryptLayerFinalizer, error) {
|
||||
var (
|
||||
encLayerReader io.Reader
|
||||
err error
|
||||
encrypted bool
|
||||
bcFin blockcipher.Finalizer
|
||||
privOptsData []byte
|
||||
pubOptsData []byte
|
||||
)
|
||||
|
||||
if ec == nil {
|
||||
return nil, nil, errors.New("EncryptConfig must not be nil")
|
||||
}
|
||||
|
||||
for annotationsID := range keyWrapperAnnotations {
|
||||
annotation := desc.Annotations[annotationsID]
|
||||
if annotation != "" {
|
||||
privOptsData, err = decryptLayerKeyOptsData(&ec.DecryptConfig, desc)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pubOptsData, err = getLayerPubOpts(desc)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// already encrypted!
|
||||
encrypted = true
|
||||
}
|
||||
}
|
||||
|
||||
if !encrypted {
|
||||
encLayerReader, bcFin, err = commonEncryptLayer(encOrPlainLayerReader, desc.Digest, blockcipher.AES256CTR)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
encLayerFinalizer := func() (map[string]string, error) {
|
||||
// If layer was already encrypted, bcFin should be nil, use existing optsData
|
||||
if bcFin != nil {
|
||||
opts, err := bcFin()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
privOptsData, err = json.Marshal(opts.Private)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not JSON marshal opts: %w", err)
|
||||
}
|
||||
pubOptsData, err = json.Marshal(opts.Public)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not JSON marshal opts: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
newAnnotations := make(map[string]string)
|
||||
keysWrapped := false
|
||||
if len(keyWrapperAnnotations) == 0 {
|
||||
return nil, errors.New("missing Annotations needed for decryption")
|
||||
}
|
||||
for annotationsID, scheme := range keyWrapperAnnotations {
|
||||
b64Annotations := desc.Annotations[annotationsID]
|
||||
keywrapper := GetKeyWrapper(scheme)
|
||||
b64Annotations, err = preWrapKeys(keywrapper, ec, b64Annotations, privOptsData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if b64Annotations != "" {
|
||||
keysWrapped = true
|
||||
newAnnotations[annotationsID] = b64Annotations
|
||||
}
|
||||
}
|
||||
|
||||
if !keysWrapped {
|
||||
return nil, errors.New("no wrapped keys produced by encryption")
|
||||
}
|
||||
newAnnotations["org.opencontainers.image.enc.pubopts"] = base64.StdEncoding.EncodeToString(pubOptsData)
|
||||
|
||||
if len(newAnnotations) == 0 {
|
||||
return nil, errors.New("no encryptor found to handle encryption")
|
||||
}
|
||||
|
||||
return newAnnotations, err
|
||||
}
|
||||
|
||||
// if nothing was encrypted, we just return encLayer = nil
|
||||
return encLayerReader, encLayerFinalizer, err
|
||||
|
||||
}
|
||||
|
||||
// preWrapKeys calls WrapKeys and handles the base64 encoding and concatenation of the
|
||||
// annotation data
|
||||
func preWrapKeys(keywrapper keywrap.KeyWrapper, ec *config.EncryptConfig, b64Annotations string, optsData []byte) (string, error) {
|
||||
newAnnotation, err := keywrapper.WrapKeys(ec, optsData)
|
||||
if err != nil || len(newAnnotation) == 0 {
|
||||
return b64Annotations, err
|
||||
}
|
||||
b64newAnnotation := base64.StdEncoding.EncodeToString(newAnnotation)
|
||||
if b64Annotations == "" {
|
||||
return b64newAnnotation, nil
|
||||
}
|
||||
return b64Annotations + "," + b64newAnnotation, nil
|
||||
}
|
||||
|
||||
// DecryptLayer decrypts a layer trying one keywrap.KeyWrapper after the other to see whether it
|
||||
// can apply the provided private key
|
||||
// If unwrapOnly is set we will only try to decrypt the layer encryption key and return
|
||||
func DecryptLayer(dc *config.DecryptConfig, encLayerReader io.Reader, desc ocispec.Descriptor, unwrapOnly bool) (io.Reader, digest.Digest, error) {
|
||||
if dc == nil {
|
||||
return nil, "", errors.New("DecryptConfig must not be nil")
|
||||
}
|
||||
privOptsData, err := decryptLayerKeyOptsData(dc, desc)
|
||||
if err != nil || unwrapOnly {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
var pubOptsData []byte
|
||||
pubOptsData, err = getLayerPubOpts(desc)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return commonDecryptLayer(encLayerReader, privOptsData, pubOptsData)
|
||||
}
|
||||
|
||||
func decryptLayerKeyOptsData(dc *config.DecryptConfig, desc ocispec.Descriptor) ([]byte, error) {
|
||||
privKeyGiven := false
|
||||
errs := ""
|
||||
if len(keyWrapperAnnotations) == 0 {
|
||||
return nil, errors.New("missing Annotations needed for decryption")
|
||||
}
|
||||
for annotationsID, scheme := range keyWrapperAnnotations {
|
||||
b64Annotation := desc.Annotations[annotationsID]
|
||||
if b64Annotation != "" {
|
||||
keywrapper := GetKeyWrapper(scheme)
|
||||
|
||||
if keywrapper.NoPossibleKeys(dc.Parameters) {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(keywrapper.GetPrivateKeys(dc.Parameters)) > 0 {
|
||||
privKeyGiven = true
|
||||
}
|
||||
optsData, err := preUnwrapKey(keywrapper, dc, b64Annotation)
|
||||
if err != nil {
|
||||
// try next keywrap.KeyWrapper
|
||||
errs += fmt.Sprintf("%s\n", err)
|
||||
continue
|
||||
}
|
||||
if optsData == nil {
|
||||
// try next keywrap.KeyWrapper
|
||||
continue
|
||||
}
|
||||
return optsData, nil
|
||||
}
|
||||
}
|
||||
if !privKeyGiven {
|
||||
return nil, fmt.Errorf("missing private key needed for decryption:\n%s", errs)
|
||||
}
|
||||
return nil, fmt.Errorf("no suitable key unwrapper found or none of the private keys could be used for decryption:\n%s", errs)
|
||||
}
|
||||
|
||||
func getLayerPubOpts(desc ocispec.Descriptor) ([]byte, error) {
|
||||
pubOptsString := desc.Annotations["org.opencontainers.image.enc.pubopts"]
|
||||
if pubOptsString == "" {
|
||||
return json.Marshal(blockcipher.PublicLayerBlockCipherOptions{})
|
||||
}
|
||||
return base64.StdEncoding.DecodeString(pubOptsString)
|
||||
}
|
||||
|
||||
// preUnwrapKey decodes the comma separated base64 strings and calls the Unwrap function
|
||||
// of the given keywrapper with it and returns the result in case the Unwrap functions
|
||||
// does not return an error. If all attempts fail, an error is returned.
|
||||
func preUnwrapKey(keywrapper keywrap.KeyWrapper, dc *config.DecryptConfig, b64Annotations string) ([]byte, error) {
|
||||
if b64Annotations == "" {
|
||||
return nil, nil
|
||||
}
|
||||
errs := ""
|
||||
for _, b64Annotation := range strings.Split(b64Annotations, ",") {
|
||||
annotation, err := base64.StdEncoding.DecodeString(b64Annotation)
|
||||
if err != nil {
|
||||
return nil, errors.New("could not base64 decode the annotation")
|
||||
}
|
||||
optsData, err := keywrapper.UnwrapKey(dc, annotation)
|
||||
if err != nil {
|
||||
errs += fmt.Sprintf("- %s\n", err)
|
||||
continue
|
||||
}
|
||||
return optsData, nil
|
||||
}
|
||||
return nil, fmt.Errorf("no suitable key found for decrypting layer key:\n%s", errs)
|
||||
}
|
||||
|
||||
// commonEncryptLayer is a function to encrypt the plain layer using a new random
|
||||
// symmetric key and return the LayerBlockCipherHandler's JSON in string form for
|
||||
// later use during decryption
|
||||
func commonEncryptLayer(plainLayerReader io.Reader, d digest.Digest, typ blockcipher.LayerCipherType) (io.Reader, blockcipher.Finalizer, error) {
|
||||
lbch, err := blockcipher.NewLayerBlockCipherHandler()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
encLayerReader, bcFin, err := lbch.Encrypt(plainLayerReader, typ)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
newBcFin := func() (blockcipher.LayerBlockCipherOptions, error) {
|
||||
lbco, err := bcFin()
|
||||
if err != nil {
|
||||
return blockcipher.LayerBlockCipherOptions{}, err
|
||||
}
|
||||
lbco.Private.Digest = d
|
||||
return lbco, nil
|
||||
}
|
||||
|
||||
return encLayerReader, newBcFin, err
|
||||
}
|
||||
|
||||
// commonDecryptLayer decrypts an encrypted layer previously encrypted with commonEncryptLayer
|
||||
// by passing along the optsData
|
||||
func commonDecryptLayer(encLayerReader io.Reader, privOptsData []byte, pubOptsData []byte) (io.Reader, digest.Digest, error) {
|
||||
privOpts := blockcipher.PrivateLayerBlockCipherOptions{}
|
||||
err := json.Unmarshal(privOptsData, &privOpts)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("could not JSON unmarshal privOptsData: %w", err)
|
||||
}
|
||||
|
||||
lbch, err := blockcipher.NewLayerBlockCipherHandler()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
pubOpts := blockcipher.PublicLayerBlockCipherOptions{}
|
||||
if len(pubOptsData) > 0 {
|
||||
err := json.Unmarshal(pubOptsData, &pubOpts)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("could not JSON unmarshal pubOptsData: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
opts := blockcipher.LayerBlockCipherOptions{
|
||||
Private: privOpts,
|
||||
Public: pubOpts,
|
||||
}
|
||||
|
||||
plainLayerReader, opts, err := lbch.Decrypt(encLayerReader, opts)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return plainLayerReader, opts.Private.Digest, nil
|
||||
}
|
||||
|
||||
// FilterOutAnnotations filters out the annotations belonging to the image encryption 'namespace'
|
||||
// and returns a map with those taken out
|
||||
func FilterOutAnnotations(annotations map[string]string) map[string]string {
|
||||
a := make(map[string]string)
|
||||
if len(annotations) > 0 {
|
||||
for k, v := range annotations {
|
||||
if strings.HasPrefix(k, "org.opencontainers.image.enc.") {
|
||||
continue
|
||||
}
|
||||
a[k] = v
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
432
vendor/github.com/containers/ocicrypt/gpg.go
generated
vendored
Normal file
432
vendor/github.com/containers/ocicrypt/gpg.go
generated
vendored
Normal file
@ -0,0 +1,432 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ocicrypt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
// GPGVersion enum representing the GPG client version to use.
|
||||
type GPGVersion int
|
||||
|
||||
const (
|
||||
// GPGv2 signifies gpgv2+
|
||||
GPGv2 GPGVersion = iota
|
||||
// GPGv1 signifies gpgv1+
|
||||
GPGv1
|
||||
// GPGVersionUndetermined signifies gpg client version undetermined
|
||||
GPGVersionUndetermined
|
||||
)
|
||||
|
||||
// GPGClient defines an interface for wrapping the gpg command line tools
|
||||
type GPGClient interface {
|
||||
// ReadGPGPubRingFile gets the byte sequence of the gpg public keyring
|
||||
ReadGPGPubRingFile() ([]byte, error)
|
||||
// GetGPGPrivateKey gets the private key bytes of a keyid given a passphrase
|
||||
GetGPGPrivateKey(keyid uint64, passphrase string) ([]byte, error)
|
||||
// GetSecretKeyDetails gets the details of a secret key
|
||||
GetSecretKeyDetails(keyid uint64) ([]byte, bool, error)
|
||||
// GetKeyDetails gets the details of a public key
|
||||
GetKeyDetails(keyid uint64) ([]byte, bool, error)
|
||||
// ResolveRecipients resolves PGP key ids to user names
|
||||
ResolveRecipients([]string) []string
|
||||
}
|
||||
|
||||
// gpgClient contains generic gpg client information
|
||||
type gpgClient struct {
|
||||
gpgHomeDir string
|
||||
}
|
||||
|
||||
// gpgv2Client is a gpg2 client
|
||||
type gpgv2Client struct {
|
||||
gpgClient
|
||||
}
|
||||
|
||||
// gpgv1Client is a gpg client
|
||||
type gpgv1Client struct {
|
||||
gpgClient
|
||||
}
|
||||
|
||||
// GuessGPGVersion guesses the version of gpg. Defaults to gpg2 if exists, if
|
||||
// not defaults to regular gpg.
|
||||
func GuessGPGVersion() GPGVersion {
|
||||
if err := exec.Command("gpg2", "--version").Run(); err == nil {
|
||||
return GPGv2
|
||||
} else if err := exec.Command("gpg", "--version").Run(); err == nil {
|
||||
return GPGv1
|
||||
} else {
|
||||
return GPGVersionUndetermined
|
||||
}
|
||||
}
|
||||
|
||||
// NewGPGClient creates a new GPGClient object representing the given version
|
||||
// and using the given home directory
|
||||
func NewGPGClient(gpgVersion, gpgHomeDir string) (GPGClient, error) {
|
||||
v := new(GPGVersion)
|
||||
switch gpgVersion {
|
||||
case "v1":
|
||||
*v = GPGv1
|
||||
case "v2":
|
||||
*v = GPGv2
|
||||
default:
|
||||
v = nil
|
||||
}
|
||||
return newGPGClient(v, gpgHomeDir)
|
||||
}
|
||||
|
||||
func newGPGClient(version *GPGVersion, homedir string) (GPGClient, error) {
|
||||
var gpgVersion GPGVersion
|
||||
if version != nil {
|
||||
gpgVersion = *version
|
||||
} else {
|
||||
gpgVersion = GuessGPGVersion()
|
||||
}
|
||||
|
||||
switch gpgVersion {
|
||||
case GPGv1:
|
||||
return &gpgv1Client{
|
||||
gpgClient: gpgClient{gpgHomeDir: homedir},
|
||||
}, nil
|
||||
case GPGv2:
|
||||
return &gpgv2Client{
|
||||
gpgClient: gpgClient{gpgHomeDir: homedir},
|
||||
}, nil
|
||||
case GPGVersionUndetermined:
|
||||
return nil, fmt.Errorf("unable to determine GPG version")
|
||||
default:
|
||||
return nil, fmt.Errorf("unhandled case: NewGPGClient")
|
||||
}
|
||||
}
|
||||
|
||||
// GetGPGPrivateKey gets the bytes of a specified keyid, supplying a passphrase
|
||||
func (gc *gpgv2Client) GetGPGPrivateKey(keyid uint64, passphrase string) ([]byte, error) {
|
||||
var args []string
|
||||
|
||||
if gc.gpgHomeDir != "" {
|
||||
args = append(args, []string{"--homedir", gc.gpgHomeDir}...)
|
||||
}
|
||||
|
||||
rfile, wfile, err := os.Pipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create pipe: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
rfile.Close()
|
||||
wfile.Close()
|
||||
}()
|
||||
// fill pipe in background
|
||||
go func(passphrase string) {
|
||||
_, _ = wfile.Write([]byte(passphrase))
|
||||
wfile.Close()
|
||||
}(passphrase)
|
||||
|
||||
args = append(args, []string{"--pinentry-mode", "loopback", "--batch", "--passphrase-fd", fmt.Sprintf("%d", 3), "--export-secret-key", fmt.Sprintf("0x%x", keyid)}...)
|
||||
|
||||
cmd := exec.Command("gpg2", args...)
|
||||
cmd.ExtraFiles = []*os.File{rfile}
|
||||
|
||||
return runGPGGetOutput(cmd)
|
||||
}
|
||||
|
||||
// ReadGPGPubRingFile reads the GPG public key ring file
|
||||
func (gc *gpgv2Client) ReadGPGPubRingFile() ([]byte, error) {
|
||||
var args []string
|
||||
|
||||
if gc.gpgHomeDir != "" {
|
||||
args = append(args, []string{"--homedir", gc.gpgHomeDir}...)
|
||||
}
|
||||
args = append(args, []string{"--batch", "--export"}...)
|
||||
|
||||
cmd := exec.Command("gpg2", args...)
|
||||
|
||||
return runGPGGetOutput(cmd)
|
||||
}
|
||||
|
||||
func (gc *gpgv2Client) getKeyDetails(option string, keyid uint64) ([]byte, bool, error) {
|
||||
var args []string
|
||||
|
||||
if gc.gpgHomeDir != "" {
|
||||
args = []string{"--homedir", gc.gpgHomeDir}
|
||||
}
|
||||
args = append(args, option, fmt.Sprintf("0x%x", keyid))
|
||||
|
||||
cmd := exec.Command("gpg2", args...)
|
||||
|
||||
keydata, err := runGPGGetOutput(cmd)
|
||||
return keydata, err == nil, err
|
||||
}
|
||||
|
||||
// GetSecretKeyDetails retrieves the secret key details of key with keyid.
|
||||
// returns a byte array of the details and a bool if the key exists
|
||||
func (gc *gpgv2Client) GetSecretKeyDetails(keyid uint64) ([]byte, bool, error) {
|
||||
return gc.getKeyDetails("-K", keyid)
|
||||
}
|
||||
|
||||
// GetKeyDetails retrieves the public key details of key with keyid.
|
||||
// returns a byte array of the details and a bool if the key exists
|
||||
func (gc *gpgv2Client) GetKeyDetails(keyid uint64) ([]byte, bool, error) {
|
||||
return gc.getKeyDetails("-k", keyid)
|
||||
}
|
||||
|
||||
// ResolveRecipients converts PGP keyids to email addresses, if possible
|
||||
func (gc *gpgv2Client) ResolveRecipients(recipients []string) []string {
|
||||
return resolveRecipients(gc, recipients)
|
||||
}
|
||||
|
||||
// GetGPGPrivateKey gets the bytes of a specified keyid, supplying a passphrase
|
||||
func (gc *gpgv1Client) GetGPGPrivateKey(keyid uint64, _ string) ([]byte, error) {
|
||||
var args []string
|
||||
|
||||
if gc.gpgHomeDir != "" {
|
||||
args = append(args, []string{"--homedir", gc.gpgHomeDir}...)
|
||||
}
|
||||
args = append(args, []string{"--batch", "--export-secret-key", fmt.Sprintf("0x%x", keyid)}...)
|
||||
|
||||
cmd := exec.Command("gpg", args...)
|
||||
|
||||
return runGPGGetOutput(cmd)
|
||||
}
|
||||
|
||||
// ReadGPGPubRingFile reads the GPG public key ring file
|
||||
func (gc *gpgv1Client) ReadGPGPubRingFile() ([]byte, error) {
|
||||
var args []string
|
||||
|
||||
if gc.gpgHomeDir != "" {
|
||||
args = append(args, []string{"--homedir", gc.gpgHomeDir}...)
|
||||
}
|
||||
args = append(args, []string{"--batch", "--export"}...)
|
||||
|
||||
cmd := exec.Command("gpg", args...)
|
||||
|
||||
return runGPGGetOutput(cmd)
|
||||
}
|
||||
|
||||
func (gc *gpgv1Client) getKeyDetails(option string, keyid uint64) ([]byte, bool, error) {
|
||||
var args []string
|
||||
|
||||
if gc.gpgHomeDir != "" {
|
||||
args = []string{"--homedir", gc.gpgHomeDir}
|
||||
}
|
||||
args = append(args, option, fmt.Sprintf("0x%x", keyid))
|
||||
|
||||
cmd := exec.Command("gpg", args...)
|
||||
|
||||
keydata, err := runGPGGetOutput(cmd)
|
||||
|
||||
return keydata, err == nil, err
|
||||
}
|
||||
|
||||
// GetSecretKeyDetails retrieves the secret key details of key with keyid.
|
||||
// returns a byte array of the details and a bool if the key exists
|
||||
func (gc *gpgv1Client) GetSecretKeyDetails(keyid uint64) ([]byte, bool, error) {
|
||||
return gc.getKeyDetails("-K", keyid)
|
||||
}
|
||||
|
||||
// GetKeyDetails retrieves the public key details of key with keyid.
|
||||
// returns a byte array of the details and a bool if the key exists
|
||||
func (gc *gpgv1Client) GetKeyDetails(keyid uint64) ([]byte, bool, error) {
|
||||
return gc.getKeyDetails("-k", keyid)
|
||||
}
|
||||
|
||||
// ResolveRecipients converts PGP keyids to email addresses, if possible
|
||||
func (gc *gpgv1Client) ResolveRecipients(recipients []string) []string {
|
||||
return resolveRecipients(gc, recipients)
|
||||
}
|
||||
|
||||
// runGPGGetOutput runs the GPG commandline and returns stdout as byte array
|
||||
// and any stderr in the error
|
||||
func runGPGGetOutput(cmd *exec.Cmd) ([]byte, error) {
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stdoutstr, err2 := io.ReadAll(stdout)
|
||||
stderrstr, _ := io.ReadAll(stderr)
|
||||
|
||||
if err := cmd.Wait(); err != nil {
|
||||
return nil, fmt.Errorf("error from %s: %s", cmd.Path, string(stderrstr))
|
||||
}
|
||||
|
||||
return stdoutstr, err2
|
||||
}
|
||||
|
||||
// resolveRecipients walks the list of recipients and attempts to convert
|
||||
// all keyIds to email addresses; if something goes wrong during the
|
||||
// conversion of a recipient, the original string is returned for that
|
||||
// recpient
|
||||
func resolveRecipients(gc GPGClient, recipients []string) []string {
|
||||
var result []string
|
||||
|
||||
for _, recipient := range recipients {
|
||||
keyID, err := strconv.ParseUint(recipient, 0, 64)
|
||||
if err != nil {
|
||||
result = append(result, recipient)
|
||||
} else {
|
||||
details, found, _ := gc.GetKeyDetails(keyID)
|
||||
if !found {
|
||||
result = append(result, recipient)
|
||||
} else {
|
||||
email := extractEmailFromDetails(details)
|
||||
if email == "" {
|
||||
result = append(result, recipient)
|
||||
} else {
|
||||
result = append(result, email)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var (
|
||||
onceRegexp sync.Once
|
||||
emailPattern *regexp.Regexp
|
||||
)
|
||||
|
||||
func extractEmailFromDetails(details []byte) string {
|
||||
onceRegexp.Do(func() {
|
||||
emailPattern = regexp.MustCompile(`uid\s+\[.*\]\s.*\s<(?P<email>.+)>`)
|
||||
})
|
||||
loc := emailPattern.FindSubmatchIndex(details)
|
||||
if len(loc) == 0 {
|
||||
return ""
|
||||
}
|
||||
return string(emailPattern.Expand(nil, []byte("$email"), details, loc))
|
||||
}
|
||||
|
||||
// uint64ToStringArray converts an array of uint64's to an array of strings
|
||||
// by applying a format string to each uint64
|
||||
func uint64ToStringArray(format string, in []uint64) []string {
|
||||
var ret []string
|
||||
|
||||
for _, v := range in {
|
||||
ret = append(ret, fmt.Sprintf(format, v))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// GPGGetPrivateKey walks the list of layerInfos and tries to decrypt the
|
||||
// wrapped symmetric keys. For this it determines whether a private key is
|
||||
// in the GPGVault or on this system and prompts for the passwords for those
|
||||
// that are available. If we do not find a private key on the system for
|
||||
// getting to the symmetric key of a layer then an error is generated.
|
||||
func GPGGetPrivateKey(descs []ocispec.Descriptor, gpgClient GPGClient, gpgVault GPGVault, mustFindKey bool) (gpgPrivKeys [][]byte, gpgPrivKeysPwds [][]byte, err error) {
|
||||
// PrivateKeyData describes a private key
|
||||
type PrivateKeyData struct {
|
||||
KeyData []byte
|
||||
KeyDataPassword []byte
|
||||
}
|
||||
var pkd PrivateKeyData
|
||||
keyIDPasswordMap := make(map[uint64]PrivateKeyData)
|
||||
|
||||
for _, desc := range descs {
|
||||
for scheme, b64pgpPackets := range GetWrappedKeysMap(desc) {
|
||||
if scheme != "pgp" {
|
||||
continue
|
||||
}
|
||||
keywrapper := GetKeyWrapper(scheme)
|
||||
if keywrapper == nil {
|
||||
return nil, nil, fmt.Errorf("could not get KeyWrapper for %s", scheme)
|
||||
}
|
||||
keyIds, err := keywrapper.GetKeyIdsFromPacket(b64pgpPackets)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, keyid := range keyIds {
|
||||
// do we have this key? -- first check the vault
|
||||
if gpgVault != nil {
|
||||
_, keydata := gpgVault.GetGPGPrivateKey(keyid)
|
||||
if len(keydata) > 0 {
|
||||
pkd = PrivateKeyData{
|
||||
KeyData: keydata,
|
||||
KeyDataPassword: nil, // password not supported in this case
|
||||
}
|
||||
keyIDPasswordMap[keyid] = pkd
|
||||
found = true
|
||||
break
|
||||
}
|
||||
} else if gpgClient != nil {
|
||||
// check the local system's gpg installation
|
||||
keyinfo, haveKey, _ := gpgClient.GetSecretKeyDetails(keyid)
|
||||
// this may fail if the key is not here; we ignore the error
|
||||
if !haveKey {
|
||||
// key not on this system
|
||||
continue
|
||||
}
|
||||
|
||||
_, found = keyIDPasswordMap[keyid]
|
||||
if !found {
|
||||
fmt.Printf("Passphrase required for Key id 0x%x: \n%v", keyid, string(keyinfo))
|
||||
fmt.Printf("Enter passphrase for key with Id 0x%x: ", keyid)
|
||||
|
||||
password, err := term.ReadPassword(int(os.Stdin.Fd()))
|
||||
fmt.Printf("\n")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
keydata, err := gpgClient.GetGPGPrivateKey(keyid, string(password))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pkd = PrivateKeyData{
|
||||
KeyData: keydata,
|
||||
KeyDataPassword: password,
|
||||
}
|
||||
keyIDPasswordMap[keyid] = pkd
|
||||
found = true
|
||||
}
|
||||
break
|
||||
} else {
|
||||
return nil, nil, errors.New("no GPGVault or GPGClient passed")
|
||||
}
|
||||
}
|
||||
if !found && len(b64pgpPackets) > 0 && mustFindKey {
|
||||
ids := uint64ToStringArray("0x%x", keyIds)
|
||||
|
||||
return nil, nil, fmt.Errorf("missing key for decryption of layer %x of %s. Need one of the following keys: %s", desc.Digest, desc.Platform, strings.Join(ids, ", "))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, pkd := range keyIDPasswordMap {
|
||||
gpgPrivKeys = append(gpgPrivKeys, pkd.KeyData)
|
||||
gpgPrivKeysPwds = append(gpgPrivKeysPwds, pkd.KeyDataPassword)
|
||||
}
|
||||
|
||||
return gpgPrivKeys, gpgPrivKeysPwds, nil
|
||||
}
|
100
vendor/github.com/containers/ocicrypt/gpgvault.go
generated
vendored
Normal file
100
vendor/github.com/containers/ocicrypt/gpgvault.go
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ocicrypt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"golang.org/x/crypto/openpgp/packet"
|
||||
)
|
||||
|
||||
// GPGVault defines an interface for wrapping multiple secret key rings
|
||||
type GPGVault interface {
|
||||
// AddSecretKeyRingData adds a secret keyring via its raw byte array
|
||||
AddSecretKeyRingData(gpgSecretKeyRingData []byte) error
|
||||
// AddSecretKeyRingDataArray adds secret keyring via its raw byte arrays
|
||||
AddSecretKeyRingDataArray(gpgSecretKeyRingDataArray [][]byte) error
|
||||
// AddSecretKeyRingFiles adds secret keyrings given their filenames
|
||||
AddSecretKeyRingFiles(filenames []string) error
|
||||
// GetGPGPrivateKey gets the private key bytes of a keyid given a passphrase
|
||||
GetGPGPrivateKey(keyid uint64) ([]openpgp.Key, []byte)
|
||||
}
|
||||
|
||||
// gpgVault wraps an array of gpgSecretKeyRing
|
||||
type gpgVault struct {
|
||||
entityLists []openpgp.EntityList
|
||||
keyDataList [][]byte // the raw data original passed in
|
||||
}
|
||||
|
||||
// NewGPGVault creates an empty GPGVault
|
||||
func NewGPGVault() GPGVault {
|
||||
return &gpgVault{}
|
||||
}
|
||||
|
||||
// AddSecretKeyRingData adds a secret keyring's to the gpgVault; the raw byte
|
||||
// array read from the file must be passed and will be parsed by this function
|
||||
func (g *gpgVault) AddSecretKeyRingData(gpgSecretKeyRingData []byte) error {
|
||||
// read the private keys
|
||||
r := bytes.NewReader(gpgSecretKeyRingData)
|
||||
entityList, err := openpgp.ReadKeyRing(r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read keyring: %w", err)
|
||||
}
|
||||
g.entityLists = append(g.entityLists, entityList)
|
||||
g.keyDataList = append(g.keyDataList, gpgSecretKeyRingData)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddSecretKeyRingDataArray adds secret keyrings to the gpgVault; the raw byte
|
||||
// arrays read from files must be passed
|
||||
func (g *gpgVault) AddSecretKeyRingDataArray(gpgSecretKeyRingDataArray [][]byte) error {
|
||||
for _, gpgSecretKeyRingData := range gpgSecretKeyRingDataArray {
|
||||
if err := g.AddSecretKeyRingData(gpgSecretKeyRingData); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddSecretKeyRingFiles adds the secret key rings given their filenames
|
||||
func (g *gpgVault) AddSecretKeyRingFiles(filenames []string) error {
|
||||
for _, filename := range filenames {
|
||||
gpgSecretKeyRingData, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = g.AddSecretKeyRingData(gpgSecretKeyRingData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGPGPrivateKey gets the bytes of a specified keyid, supplying a passphrase
|
||||
func (g *gpgVault) GetGPGPrivateKey(keyid uint64) ([]openpgp.Key, []byte) {
|
||||
for i, el := range g.entityLists {
|
||||
decKeys := el.KeysByIdUsage(keyid, packet.KeyFlagEncryptCommunications)
|
||||
if len(decKeys) > 0 {
|
||||
return decKeys, g.keyDataList[i]
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
152
vendor/github.com/containers/ocicrypt/keywrap/jwe/keywrapper_jwe.go
generated
vendored
Normal file
152
vendor/github.com/containers/ocicrypt/keywrap/jwe/keywrapper_jwe.go
generated
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package jwe
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/ocicrypt/config"
|
||||
"github.com/containers/ocicrypt/keywrap"
|
||||
"github.com/containers/ocicrypt/utils"
|
||||
"github.com/go-jose/go-jose/v3"
|
||||
)
|
||||
|
||||
type jweKeyWrapper struct {
|
||||
}
|
||||
|
||||
func (kw *jweKeyWrapper) GetAnnotationID() string {
|
||||
return "org.opencontainers.image.enc.keys.jwe"
|
||||
}
|
||||
|
||||
// NewKeyWrapper returns a new key wrapping interface using jwe
|
||||
func NewKeyWrapper() keywrap.KeyWrapper {
|
||||
return &jweKeyWrapper{}
|
||||
}
|
||||
|
||||
// WrapKeys wraps the session key for recpients and encrypts the optsData, which
|
||||
// describe the symmetric key used for encrypting the layer
|
||||
func (kw *jweKeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
|
||||
var joseRecipients []jose.Recipient
|
||||
|
||||
err := addPubKeys(&joseRecipients, ec.Parameters["pubkeys"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// no recipients is not an error...
|
||||
if len(joseRecipients) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
encrypter, err := jose.NewMultiEncrypter(jose.A256GCM, joseRecipients, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("jose.NewMultiEncrypter failed: %w", err)
|
||||
}
|
||||
jwe, err := encrypter.Encrypt(optsData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("JWE Encrypt failed: %w", err)
|
||||
}
|
||||
return []byte(jwe.FullSerialize()), nil
|
||||
}
|
||||
|
||||
func (kw *jweKeyWrapper) UnwrapKey(dc *config.DecryptConfig, jweString []byte) ([]byte, error) {
|
||||
jwe, err := jose.ParseEncrypted(string(jweString))
|
||||
if err != nil {
|
||||
return nil, errors.New("jose.ParseEncrypted failed")
|
||||
}
|
||||
|
||||
privKeys := kw.GetPrivateKeys(dc.Parameters)
|
||||
if len(privKeys) == 0 {
|
||||
return nil, errors.New("No private keys found for JWE decryption")
|
||||
}
|
||||
privKeysPasswords := kw.getPrivateKeysPasswords(dc.Parameters)
|
||||
if len(privKeysPasswords) != len(privKeys) {
|
||||
return nil, errors.New("Private key password array length must be same as that of private keys")
|
||||
}
|
||||
|
||||
for idx, privKey := range privKeys {
|
||||
key, err := utils.ParsePrivateKey(privKey, privKeysPasswords[idx], "JWE")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, _, plain, err := jwe.DecryptMulti(key)
|
||||
if err == nil {
|
||||
return plain, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("JWE: No suitable private key found for decryption")
|
||||
}
|
||||
|
||||
func (kw *jweKeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool {
|
||||
return len(kw.GetPrivateKeys(dcparameters)) == 0
|
||||
}
|
||||
|
||||
func (kw *jweKeyWrapper) GetPrivateKeys(dcparameters map[string][][]byte) [][]byte {
|
||||
return dcparameters["privkeys"]
|
||||
}
|
||||
|
||||
func (kw *jweKeyWrapper) getPrivateKeysPasswords(dcparameters map[string][][]byte) [][]byte {
|
||||
return dcparameters["privkeys-passwords"]
|
||||
}
|
||||
|
||||
func (kw *jweKeyWrapper) GetKeyIdsFromPacket(b64jwes string) ([]uint64, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (kw *jweKeyWrapper) GetRecipients(b64jwes string) ([]string, error) {
|
||||
return []string{"[jwe]"}, nil
|
||||
}
|
||||
|
||||
func addPubKeys(joseRecipients *[]jose.Recipient, pubKeys [][]byte) error {
|
||||
if len(pubKeys) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, pubKey := range pubKeys {
|
||||
key, err := utils.ParsePublicKey(pubKey, "JWE")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
alg := jose.RSA_OAEP
|
||||
switch key := key.(type) {
|
||||
case *ecdsa.PublicKey:
|
||||
alg = jose.ECDH_ES_A256KW
|
||||
case *jose.JSONWebKey:
|
||||
if key.Algorithm != "" {
|
||||
alg = jose.KeyAlgorithm(key.Algorithm)
|
||||
switch alg {
|
||||
/* accepted algorithms */
|
||||
case jose.RSA_OAEP:
|
||||
case jose.RSA_OAEP_256:
|
||||
case jose.ECDH_ES_A128KW:
|
||||
case jose.ECDH_ES_A192KW:
|
||||
case jose.ECDH_ES_A256KW:
|
||||
/* all others are rejected */
|
||||
default:
|
||||
return fmt.Errorf("%s is an unsupported JWE key algorithm", alg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*joseRecipients = append(*joseRecipients, jose.Recipient{
|
||||
Algorithm: alg,
|
||||
Key: key,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
244
vendor/github.com/containers/ocicrypt/keywrap/keyprovider/keyprovider.go
generated
vendored
Normal file
244
vendor/github.com/containers/ocicrypt/keywrap/keyprovider/keyprovider.go
generated
vendored
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package keyprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/ocicrypt/config"
|
||||
keyproviderconfig "github.com/containers/ocicrypt/config/keyprovider-config"
|
||||
"github.com/containers/ocicrypt/keywrap"
|
||||
"github.com/containers/ocicrypt/utils"
|
||||
keyproviderpb "github.com/containers/ocicrypt/utils/keyprovider"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type keyProviderKeyWrapper struct {
|
||||
provider string
|
||||
attrs keyproviderconfig.KeyProviderAttrs
|
||||
}
|
||||
|
||||
func (kw *keyProviderKeyWrapper) GetAnnotationID() string {
|
||||
return "org.opencontainers.image.enc.keys.provider." + kw.provider
|
||||
}
|
||||
|
||||
// NewKeyWrapper returns a new key wrapping interface using keyprovider
|
||||
func NewKeyWrapper(p string, a keyproviderconfig.KeyProviderAttrs) keywrap.KeyWrapper {
|
||||
return &keyProviderKeyWrapper{provider: p, attrs: a}
|
||||
}
|
||||
|
||||
type KeyProviderKeyWrapProtocolOperation string
|
||||
|
||||
var (
|
||||
OpKeyWrap KeyProviderKeyWrapProtocolOperation = "keywrap"
|
||||
OpKeyUnwrap KeyProviderKeyWrapProtocolOperation = "keyunwrap"
|
||||
)
|
||||
|
||||
// KeyProviderKeyWrapProtocolInput defines the input to the key provider binary or grpc method.
|
||||
type KeyProviderKeyWrapProtocolInput struct {
|
||||
// Operation is either "keywrap" or "keyunwrap"
|
||||
Operation KeyProviderKeyWrapProtocolOperation `json:"op"`
|
||||
// KeyWrapParams encodes the arguments to key wrap if operation is set to wrap
|
||||
KeyWrapParams KeyWrapParams `json:"keywrapparams,omitempty"`
|
||||
// KeyUnwrapParams encodes the arguments to key unwrap if operation is set to unwrap
|
||||
KeyUnwrapParams KeyUnwrapParams `json:"keyunwrapparams,omitempty"`
|
||||
}
|
||||
|
||||
// KeyProviderKeyWrapProtocolOutput defines the output of the key provider binary or grpc method.
|
||||
type KeyProviderKeyWrapProtocolOutput struct {
|
||||
// KeyWrapResult encodes the results to key wrap if operation is to wrap
|
||||
KeyWrapResults KeyWrapResults `json:"keywrapresults,omitempty"`
|
||||
// KeyUnwrapResult encodes the result to key unwrap if operation is to unwrap
|
||||
KeyUnwrapResults KeyUnwrapResults `json:"keyunwrapresults,omitempty"`
|
||||
}
|
||||
|
||||
type KeyWrapParams struct {
|
||||
Ec *config.EncryptConfig `json:"ec"`
|
||||
OptsData []byte `json:"optsdata"`
|
||||
}
|
||||
|
||||
type KeyUnwrapParams struct {
|
||||
Dc *config.DecryptConfig `json:"dc"`
|
||||
Annotation []byte `json:"annotation"`
|
||||
}
|
||||
|
||||
type KeyUnwrapResults struct {
|
||||
OptsData []byte `json:"optsdata"`
|
||||
}
|
||||
|
||||
type KeyWrapResults struct {
|
||||
Annotation []byte `json:"annotation"`
|
||||
}
|
||||
|
||||
var runner utils.CommandExecuter
|
||||
|
||||
func init() {
|
||||
runner = utils.Runner{}
|
||||
}
|
||||
|
||||
// WrapKeys calls appropriate binary executable/grpc server for wrapping the session key for recipients and gets encrypted optsData, which
|
||||
// describe the symmetric key used for encrypting the layer
|
||||
func (kw *keyProviderKeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
|
||||
|
||||
input, err := json.Marshal(KeyProviderKeyWrapProtocolInput{
|
||||
Operation: OpKeyWrap,
|
||||
KeyWrapParams: KeyWrapParams{
|
||||
Ec: ec,
|
||||
OptsData: optsData,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, ok := ec.Parameters[kw.provider]; ok {
|
||||
if kw.attrs.Command != nil {
|
||||
protocolOuput, err := getProviderCommandOutput(input, kw.attrs.Command)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while retrieving keyprovider protocol command output: %w", err)
|
||||
}
|
||||
return protocolOuput.KeyWrapResults.Annotation, nil
|
||||
} else if kw.attrs.Grpc != "" {
|
||||
protocolOuput, err := getProviderGRPCOutput(input, kw.attrs.Grpc, OpKeyWrap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while retrieving keyprovider protocol grpc output: %w", err)
|
||||
}
|
||||
|
||||
return protocolOuput.KeyWrapResults.Annotation, nil
|
||||
} else {
|
||||
return nil, errors.New("Unsupported keyprovider invocation. Supported invocation methods are grpc and cmd")
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// UnwrapKey calls appropriate binary executable/grpc server for unwrapping the session key based on the protocol given in annotation for recipients and gets decrypted optsData,
|
||||
// which describe the symmetric key used for decrypting the layer
|
||||
func (kw *keyProviderKeyWrapper) UnwrapKey(dc *config.DecryptConfig, jsonString []byte) ([]byte, error) {
|
||||
input, err := json.Marshal(KeyProviderKeyWrapProtocolInput{
|
||||
Operation: OpKeyUnwrap,
|
||||
KeyUnwrapParams: KeyUnwrapParams{
|
||||
Dc: dc,
|
||||
Annotation: jsonString,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if kw.attrs.Command != nil {
|
||||
protocolOuput, err := getProviderCommandOutput(input, kw.attrs.Command)
|
||||
if err != nil {
|
||||
// If err is not nil, then ignore it and continue with rest of the given keyproviders
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return protocolOuput.KeyUnwrapResults.OptsData, nil
|
||||
} else if kw.attrs.Grpc != "" {
|
||||
protocolOuput, err := getProviderGRPCOutput(input, kw.attrs.Grpc, OpKeyUnwrap)
|
||||
if err != nil {
|
||||
// If err is not nil, then ignore it and continue with rest of the given keyproviders
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return protocolOuput.KeyUnwrapResults.OptsData, nil
|
||||
} else {
|
||||
return nil, errors.New("Unsupported keyprovider invocation. Supported invocation methods are grpc and cmd")
|
||||
}
|
||||
}
|
||||
|
||||
func getProviderGRPCOutput(input []byte, connString string, operation KeyProviderKeyWrapProtocolOperation) (*KeyProviderKeyWrapProtocolOutput, error) {
|
||||
var protocolOuput KeyProviderKeyWrapProtocolOutput
|
||||
var grpcOutput *keyproviderpb.KeyProviderKeyWrapProtocolOutput
|
||||
cc, err := grpc.Dial(connString, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while dialing rpc server: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
derr := cc.Close()
|
||||
if derr != nil {
|
||||
log.WithError(derr).Error("Error closing grpc socket")
|
||||
}
|
||||
}()
|
||||
|
||||
client := keyproviderpb.NewKeyProviderServiceClient(cc)
|
||||
req := &keyproviderpb.KeyProviderKeyWrapProtocolInput{
|
||||
KeyProviderKeyWrapProtocolInput: input,
|
||||
}
|
||||
|
||||
if operation == OpKeyWrap {
|
||||
grpcOutput, err = client.WrapKey(context.Background(), req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error from grpc method: %w", err)
|
||||
}
|
||||
} else if operation == OpKeyUnwrap {
|
||||
grpcOutput, err = client.UnWrapKey(context.Background(), req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error from grpc method: %w", err)
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("Unsupported operation")
|
||||
}
|
||||
|
||||
respBytes := grpcOutput.GetKeyProviderKeyWrapProtocolOutput()
|
||||
err = json.Unmarshal(respBytes, &protocolOuput)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error while unmarshalling grpc method output: %w", err)
|
||||
}
|
||||
|
||||
return &protocolOuput, nil
|
||||
}
|
||||
|
||||
func getProviderCommandOutput(input []byte, command *keyproviderconfig.Command) (*KeyProviderKeyWrapProtocolOutput, error) {
|
||||
var protocolOuput KeyProviderKeyWrapProtocolOutput
|
||||
// Convert interface to command structure
|
||||
respBytes, err := runner.Exec(command.Path, command.Args, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(respBytes, &protocolOuput)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error while unmarshalling binary executable command output: %w", err)
|
||||
}
|
||||
return &protocolOuput, nil
|
||||
}
|
||||
|
||||
// Return false as it is not applicable to keyprovider protocol
|
||||
func (kw *keyProviderKeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Return nil as it is not applicable to keyprovider protocol
|
||||
func (kw *keyProviderKeyWrapper) GetPrivateKeys(dcparameters map[string][][]byte) [][]byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Return nil as it is not applicable to keyprovider protocol
|
||||
func (kw *keyProviderKeyWrapper) GetKeyIdsFromPacket(_ string) ([]uint64, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Return nil as it is not applicable to keyprovider protocol
|
||||
func (kw *keyProviderKeyWrapper) GetRecipients(_ string) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
48
vendor/github.com/containers/ocicrypt/keywrap/keywrap.go
generated
vendored
Normal file
48
vendor/github.com/containers/ocicrypt/keywrap/keywrap.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package keywrap
|
||||
|
||||
import (
|
||||
"github.com/containers/ocicrypt/config"
|
||||
)
|
||||
|
||||
// KeyWrapper is the interface used for wrapping keys using
|
||||
// a specific encryption technology (pgp, jwe)
|
||||
type KeyWrapper interface {
|
||||
WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error)
|
||||
UnwrapKey(dc *config.DecryptConfig, annotation []byte) ([]byte, error)
|
||||
GetAnnotationID() string
|
||||
|
||||
// NoPossibleKeys returns true if there is no possibility of performing
|
||||
// decryption for parameters provided.
|
||||
NoPossibleKeys(dcparameters map[string][][]byte) bool
|
||||
|
||||
// GetPrivateKeys (optional) gets the array of private keys. It is an optional implementation
|
||||
// as in some key services, a private key may not be exportable (i.e. HSM)
|
||||
// If not implemented, return nil
|
||||
GetPrivateKeys(dcparameters map[string][][]byte) [][]byte
|
||||
|
||||
// GetKeyIdsFromPacket (optional) gets a list of key IDs. This is optional as some encryption
|
||||
// schemes may not have a notion of key IDs
|
||||
// If not implemented, return the nil slice
|
||||
GetKeyIdsFromPacket(packet string) ([]uint64, error)
|
||||
|
||||
// GetRecipients (optional) gets a list of recipients. It is optional due to the validity of
|
||||
// recipients in a particular encryptiong scheme
|
||||
// If not implemented, return the nil slice
|
||||
GetRecipients(packet string) ([]string, error)
|
||||
}
|
272
vendor/github.com/containers/ocicrypt/keywrap/pgp/keywrapper_gpg.go
generated
vendored
Normal file
272
vendor/github.com/containers/ocicrypt/keywrap/pgp/keywrapper_gpg.go
generated
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pgp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/mail"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/ocicrypt/config"
|
||||
"github.com/containers/ocicrypt/keywrap"
|
||||
"golang.org/x/crypto/openpgp"
|
||||
"golang.org/x/crypto/openpgp/packet"
|
||||
)
|
||||
|
||||
type gpgKeyWrapper struct {
|
||||
}
|
||||
|
||||
// NewKeyWrapper returns a new key wrapping interface for pgp
|
||||
func NewKeyWrapper() keywrap.KeyWrapper {
|
||||
return &gpgKeyWrapper{}
|
||||
}
|
||||
|
||||
var (
|
||||
// GPGDefaultEncryptConfig is the default configuration for layer encryption/decryption
|
||||
GPGDefaultEncryptConfig = &packet.Config{
|
||||
Rand: rand.Reader,
|
||||
DefaultHash: crypto.SHA256,
|
||||
DefaultCipher: packet.CipherAES256,
|
||||
CompressionConfig: &packet.CompressionConfig{Level: 0}, // No compression
|
||||
RSABits: 2048,
|
||||
}
|
||||
)
|
||||
|
||||
func (kw *gpgKeyWrapper) GetAnnotationID() string {
|
||||
return "org.opencontainers.image.enc.keys.pgp"
|
||||
}
|
||||
|
||||
// WrapKeys wraps the session key for recpients and encrypts the optsData, which
|
||||
// describe the symmetric key used for encrypting the layer
|
||||
func (kw *gpgKeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
|
||||
ciphertext := new(bytes.Buffer)
|
||||
el, err := kw.createEntityList(ec)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create entity list: %w", err)
|
||||
}
|
||||
if len(el) == 0 {
|
||||
// nothing to do -- not an error
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
plaintextWriter, err := openpgp.Encrypt(ciphertext,
|
||||
el, /*EntityList*/
|
||||
nil, /* Sign*/
|
||||
nil, /* FileHint */
|
||||
GPGDefaultEncryptConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = plaintextWriter.Write(optsData); err != nil {
|
||||
return nil, err
|
||||
} else if err = plaintextWriter.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ciphertext.Bytes(), err
|
||||
}
|
||||
|
||||
// UnwrapKey unwraps the symmetric key with which the layer is encrypted
|
||||
// This symmetric key is encrypted in the PGP payload.
|
||||
func (kw *gpgKeyWrapper) UnwrapKey(dc *config.DecryptConfig, pgpPacket []byte) ([]byte, error) {
|
||||
pgpPrivateKeys, pgpPrivateKeysPwd, err := kw.getKeyParameters(dc.Parameters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for idx, pgpPrivateKey := range pgpPrivateKeys {
|
||||
r := bytes.NewBuffer(pgpPrivateKey)
|
||||
entityList, err := openpgp.ReadKeyRing(r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse private keys: %w", err)
|
||||
}
|
||||
|
||||
var prompt openpgp.PromptFunction
|
||||
if len(pgpPrivateKeysPwd) > idx {
|
||||
responded := false
|
||||
prompt = func(keys []openpgp.Key, symmetric bool) ([]byte, error) {
|
||||
if responded {
|
||||
return nil, fmt.Errorf("don't seem to have the right password")
|
||||
}
|
||||
responded = true
|
||||
for _, key := range keys {
|
||||
if key.PrivateKey != nil {
|
||||
_ = key.PrivateKey.Decrypt(pgpPrivateKeysPwd[idx])
|
||||
}
|
||||
}
|
||||
return pgpPrivateKeysPwd[idx], nil
|
||||
}
|
||||
}
|
||||
|
||||
r = bytes.NewBuffer(pgpPacket)
|
||||
md, err := openpgp.ReadMessage(r, entityList, prompt, GPGDefaultEncryptConfig)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// we get the plain key options back
|
||||
optsData, err := io.ReadAll(md.UnverifiedBody)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return optsData, nil
|
||||
}
|
||||
return nil, errors.New("PGP: No suitable key found to unwrap key")
|
||||
}
|
||||
|
||||
// GetKeyIdsFromWrappedKeys converts the base64 encoded PGPPacket to uint64 keyIds
|
||||
func (kw *gpgKeyWrapper) GetKeyIdsFromPacket(b64pgpPackets string) ([]uint64, error) {
|
||||
|
||||
var keyids []uint64
|
||||
for _, b64pgpPacket := range strings.Split(b64pgpPackets, ",") {
|
||||
pgpPacket, err := base64.StdEncoding.DecodeString(b64pgpPacket)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not decode base64 encoded PGP packet: %w", err)
|
||||
}
|
||||
newids, err := kw.getKeyIDs(pgpPacket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyids = append(keyids, newids...)
|
||||
}
|
||||
return keyids, nil
|
||||
}
|
||||
|
||||
// getKeyIDs parses a PGPPacket and gets the list of recipients' key IDs
|
||||
func (kw *gpgKeyWrapper) getKeyIDs(pgpPacket []byte) ([]uint64, error) {
|
||||
var keyids []uint64
|
||||
|
||||
kbuf := bytes.NewBuffer(pgpPacket)
|
||||
packets := packet.NewReader(kbuf)
|
||||
ParsePackets:
|
||||
for {
|
||||
p, err := packets.Next()
|
||||
if err == io.EOF {
|
||||
break ParsePackets
|
||||
}
|
||||
if err != nil {
|
||||
return []uint64{}, fmt.Errorf("packets.Next() failed: %w", err)
|
||||
}
|
||||
switch p := p.(type) {
|
||||
case *packet.EncryptedKey:
|
||||
keyids = append(keyids, p.KeyId)
|
||||
case *packet.SymmetricallyEncrypted:
|
||||
break ParsePackets
|
||||
}
|
||||
}
|
||||
return keyids, nil
|
||||
}
|
||||
|
||||
// GetRecipients converts the wrappedKeys to an array of recipients
|
||||
func (kw *gpgKeyWrapper) GetRecipients(b64pgpPackets string) ([]string, error) {
|
||||
keyIds, err := kw.GetKeyIdsFromPacket(b64pgpPackets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var array []string
|
||||
for _, keyid := range keyIds {
|
||||
array = append(array, "0x"+strconv.FormatUint(keyid, 16))
|
||||
}
|
||||
return array, nil
|
||||
}
|
||||
|
||||
func (kw *gpgKeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool {
|
||||
return len(kw.GetPrivateKeys(dcparameters)) == 0
|
||||
}
|
||||
|
||||
func (kw *gpgKeyWrapper) GetPrivateKeys(dcparameters map[string][][]byte) [][]byte {
|
||||
return dcparameters["gpg-privatekeys"]
|
||||
}
|
||||
|
||||
func (kw *gpgKeyWrapper) getKeyParameters(dcparameters map[string][][]byte) ([][]byte, [][]byte, error) {
|
||||
|
||||
privKeys := kw.GetPrivateKeys(dcparameters)
|
||||
if len(privKeys) == 0 {
|
||||
return nil, nil, errors.New("GPG: Missing private key parameter")
|
||||
}
|
||||
|
||||
return privKeys, dcparameters["gpg-privatekeys-passwords"], nil
|
||||
}
|
||||
|
||||
// createEntityList creates the opengpg EntityList by reading the KeyRing
|
||||
// first and then filtering out recipients' keys
|
||||
func (kw *gpgKeyWrapper) createEntityList(ec *config.EncryptConfig) (openpgp.EntityList, error) {
|
||||
pgpPubringFile := ec.Parameters["gpg-pubkeyringfile"]
|
||||
if len(pgpPubringFile) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
r := bytes.NewReader(pgpPubringFile[0])
|
||||
|
||||
entityList, err := openpgp.ReadKeyRing(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gpgRecipients := ec.Parameters["gpg-recipients"]
|
||||
if len(gpgRecipients) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rSet := make(map[string]int)
|
||||
for _, r := range gpgRecipients {
|
||||
rSet[string(r)] = 0
|
||||
}
|
||||
|
||||
var filteredList openpgp.EntityList
|
||||
for _, entity := range entityList {
|
||||
for k := range entity.Identities {
|
||||
addr, err := mail.ParseAddress(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, r := range gpgRecipients {
|
||||
recp := string(r)
|
||||
if strings.Compare(addr.Name, recp) == 0 || strings.Compare(addr.Address, recp) == 0 {
|
||||
filteredList = append(filteredList, entity)
|
||||
rSet[recp] = rSet[recp] + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure we found keys for all the Recipients...
|
||||
var buffer bytes.Buffer
|
||||
notFound := false
|
||||
buffer.WriteString("PGP: No key found for the following recipients: ")
|
||||
|
||||
for k, v := range rSet {
|
||||
if v == 0 {
|
||||
if notFound {
|
||||
buffer.WriteString(", ")
|
||||
}
|
||||
buffer.WriteString(k)
|
||||
notFound = true
|
||||
}
|
||||
}
|
||||
|
||||
if notFound {
|
||||
return nil, errors.New(buffer.String())
|
||||
}
|
||||
|
||||
return filteredList, nil
|
||||
}
|
152
vendor/github.com/containers/ocicrypt/keywrap/pkcs11/keywrapper_pkcs11.go
generated
vendored
Normal file
152
vendor/github.com/containers/ocicrypt/keywrap/pkcs11/keywrapper_pkcs11.go
generated
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pkcs11
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/ocicrypt/config"
|
||||
"github.com/containers/ocicrypt/crypto/pkcs11"
|
||||
"github.com/containers/ocicrypt/keywrap"
|
||||
"github.com/containers/ocicrypt/utils"
|
||||
)
|
||||
|
||||
type pkcs11KeyWrapper struct {
|
||||
}
|
||||
|
||||
func (kw *pkcs11KeyWrapper) GetAnnotationID() string {
|
||||
return "org.opencontainers.image.enc.keys.pkcs11"
|
||||
}
|
||||
|
||||
// NewKeyWrapper returns a new key wrapping interface using pkcs11
|
||||
func NewKeyWrapper() keywrap.KeyWrapper {
|
||||
return &pkcs11KeyWrapper{}
|
||||
}
|
||||
|
||||
// WrapKeys wraps the session key for recpients and encrypts the optsData, which
|
||||
// describe the symmetric key used for encrypting the layer
|
||||
func (kw *pkcs11KeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
|
||||
// append({}, ...) allocates a fresh backing array, and that's necessary to guarantee concurrent calls to WrapKeys (as in c/image/copy.Image)
|
||||
// can't race writing to the same backing array.
|
||||
pubKeys := append([][]byte{}, ec.Parameters["pkcs11-pubkeys"]...) // In Go 1.21, slices.Clone(ec.Parameters["pkcs11-pubkeys"])
|
||||
pubKeys = append(pubKeys, ec.Parameters["pkcs11-yamls"]...)
|
||||
pkcs11Recipients, err := addPubKeys(&ec.DecryptConfig, pubKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// no recipients is not an error...
|
||||
if len(pkcs11Recipients) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
jsonString, err := pkcs11.EncryptMultiple(pkcs11Recipients, optsData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("PKCS11 EncryptMulitple failed: %w", err)
|
||||
}
|
||||
return jsonString, nil
|
||||
}
|
||||
|
||||
func (kw *pkcs11KeyWrapper) UnwrapKey(dc *config.DecryptConfig, jsonString []byte) ([]byte, error) {
|
||||
var pkcs11PrivKeys []*pkcs11.Pkcs11KeyFileObject
|
||||
|
||||
privKeys := kw.GetPrivateKeys(dc.Parameters)
|
||||
if len(privKeys) == 0 {
|
||||
return nil, errors.New("No private keys found for PKCS11 decryption")
|
||||
}
|
||||
|
||||
p11conf, err := p11confFromParameters(dc.Parameters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, privKey := range privKeys {
|
||||
key, err := utils.ParsePrivateKey(privKey, nil, "PKCS11")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch pkcs11PrivKey := key.(type) {
|
||||
case *pkcs11.Pkcs11KeyFileObject:
|
||||
if p11conf != nil {
|
||||
pkcs11PrivKey.Uri.SetModuleDirectories(p11conf.ModuleDirectories)
|
||||
pkcs11PrivKey.Uri.SetAllowedModulePaths(p11conf.AllowedModulePaths)
|
||||
}
|
||||
pkcs11PrivKeys = append(pkcs11PrivKeys, pkcs11PrivKey)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
plaintext, err := pkcs11.Decrypt(pkcs11PrivKeys, jsonString)
|
||||
if err == nil {
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("PKCS11: No suitable private key found for decryption: %w", err)
|
||||
}
|
||||
|
||||
func (kw *pkcs11KeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool {
|
||||
return len(kw.GetPrivateKeys(dcparameters)) == 0
|
||||
}
|
||||
|
||||
func (kw *pkcs11KeyWrapper) GetPrivateKeys(dcparameters map[string][][]byte) [][]byte {
|
||||
return dcparameters["pkcs11-yamls"]
|
||||
}
|
||||
|
||||
func (kw *pkcs11KeyWrapper) GetKeyIdsFromPacket(_ string) ([]uint64, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (kw *pkcs11KeyWrapper) GetRecipients(_ string) ([]string, error) {
|
||||
return []string{"[pkcs11]"}, nil
|
||||
}
|
||||
|
||||
func addPubKeys(dc *config.DecryptConfig, pubKeys [][]byte) ([]interface{}, error) {
|
||||
var pkcs11Keys []interface{}
|
||||
|
||||
if len(pubKeys) == 0 {
|
||||
return pkcs11Keys, nil
|
||||
}
|
||||
|
||||
p11conf, err := p11confFromParameters(dc.Parameters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, pubKey := range pubKeys {
|
||||
key, err := utils.ParsePublicKey(pubKey, "PKCS11")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch pkcs11PubKey := key.(type) {
|
||||
case *pkcs11.Pkcs11KeyFileObject:
|
||||
if p11conf != nil {
|
||||
pkcs11PubKey.Uri.SetModuleDirectories(p11conf.ModuleDirectories)
|
||||
pkcs11PubKey.Uri.SetAllowedModulePaths(p11conf.AllowedModulePaths)
|
||||
}
|
||||
}
|
||||
pkcs11Keys = append(pkcs11Keys, key)
|
||||
}
|
||||
return pkcs11Keys, nil
|
||||
}
|
||||
|
||||
func p11confFromParameters(dcparameters map[string][][]byte) (*pkcs11.Pkcs11Config, error) {
|
||||
if _, ok := dcparameters["pkcs11-config"]; ok {
|
||||
return pkcs11.ParsePkcs11ConfigFile(dcparameters["pkcs11-config"][0])
|
||||
}
|
||||
return nil, nil
|
||||
}
|
137
vendor/github.com/containers/ocicrypt/keywrap/pkcs7/keywrapper_pkcs7.go
generated
vendored
Normal file
137
vendor/github.com/containers/ocicrypt/keywrap/pkcs7/keywrapper_pkcs7.go
generated
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pkcs7
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/ocicrypt/config"
|
||||
"github.com/containers/ocicrypt/keywrap"
|
||||
"github.com/containers/ocicrypt/utils"
|
||||
"go.mozilla.org/pkcs7"
|
||||
)
|
||||
|
||||
type pkcs7KeyWrapper struct {
|
||||
}
|
||||
|
||||
// NewKeyWrapper returns a new key wrapping interface using jwe
|
||||
func NewKeyWrapper() keywrap.KeyWrapper {
|
||||
return &pkcs7KeyWrapper{}
|
||||
}
|
||||
|
||||
func (kw *pkcs7KeyWrapper) GetAnnotationID() string {
|
||||
return "org.opencontainers.image.enc.keys.pkcs7"
|
||||
}
|
||||
|
||||
// WrapKeys wraps the session key for recpients and encrypts the optsData, which
|
||||
// describe the symmetric key used for encrypting the layer
|
||||
func (kw *pkcs7KeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
|
||||
x509Certs, err := collectX509s(ec.Parameters["x509s"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// no recipients is not an error...
|
||||
if len(x509Certs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
pkcs7.ContentEncryptionAlgorithm = pkcs7.EncryptionAlgorithmAES128GCM
|
||||
return pkcs7.Encrypt(optsData, x509Certs)
|
||||
}
|
||||
|
||||
func collectX509s(x509s [][]byte) ([]*x509.Certificate, error) {
|
||||
if len(x509s) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var x509Certs []*x509.Certificate
|
||||
for _, x509 := range x509s {
|
||||
x509Cert, err := utils.ParseCertificate(x509, "PKCS7")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x509Certs = append(x509Certs, x509Cert)
|
||||
}
|
||||
return x509Certs, nil
|
||||
}
|
||||
|
||||
func (kw *pkcs7KeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool {
|
||||
return len(kw.GetPrivateKeys(dcparameters)) == 0
|
||||
}
|
||||
|
||||
func (kw *pkcs7KeyWrapper) GetPrivateKeys(dcparameters map[string][][]byte) [][]byte {
|
||||
return dcparameters["privkeys"]
|
||||
}
|
||||
|
||||
func (kw *pkcs7KeyWrapper) getPrivateKeysPasswords(dcparameters map[string][][]byte) [][]byte {
|
||||
return dcparameters["privkeys-passwords"]
|
||||
}
|
||||
|
||||
// UnwrapKey unwraps the symmetric key with which the layer is encrypted
|
||||
// This symmetric key is encrypted in the PKCS7 payload.
|
||||
func (kw *pkcs7KeyWrapper) UnwrapKey(dc *config.DecryptConfig, pkcs7Packet []byte) ([]byte, error) {
|
||||
privKeys := kw.GetPrivateKeys(dc.Parameters)
|
||||
if len(privKeys) == 0 {
|
||||
return nil, errors.New("no private keys found for PKCS7 decryption")
|
||||
}
|
||||
privKeysPasswords := kw.getPrivateKeysPasswords(dc.Parameters)
|
||||
if len(privKeysPasswords) != len(privKeys) {
|
||||
return nil, errors.New("private key password array length must be same as that of private keys")
|
||||
}
|
||||
|
||||
x509Certs, err := collectX509s(dc.Parameters["x509s"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(x509Certs) == 0 {
|
||||
return nil, errors.New("no x509 certificates found needed for PKCS7 decryption")
|
||||
}
|
||||
|
||||
p7, err := pkcs7.Parse(pkcs7Packet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse PKCS7 packet: %w", err)
|
||||
}
|
||||
|
||||
for idx, privKey := range privKeys {
|
||||
key, err := utils.ParsePrivateKey(privKey, privKeysPasswords[idx], "PKCS7")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, x509Cert := range x509Certs {
|
||||
optsData, err := p7.Decrypt(x509Cert, crypto.PrivateKey(key))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return optsData, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("PKCS7: No suitable private key found for decryption")
|
||||
}
|
||||
|
||||
// GetKeyIdsFromWrappedKeys converts the base64 encoded Packet to uint64 keyIds;
|
||||
// We cannot do this with pkcs7
|
||||
func (kw *pkcs7KeyWrapper) GetKeyIdsFromPacket(b64pkcs7Packets string) ([]uint64, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetRecipients converts the wrappedKeys to an array of recipients
|
||||
// We cannot do this with pkcs7
|
||||
func (kw *pkcs7KeyWrapper) GetRecipients(b64pkcs7Packets string) ([]string, error) {
|
||||
return []string{"[pkcs7]"}, nil
|
||||
}
|
40
vendor/github.com/containers/ocicrypt/reader.go
generated
vendored
Normal file
40
vendor/github.com/containers/ocicrypt/reader.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ocicrypt
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type readerAtReader struct {
|
||||
r io.ReaderAt
|
||||
off int64
|
||||
}
|
||||
|
||||
// ReaderFromReaderAt takes an io.ReaderAt and returns an io.Reader
|
||||
func ReaderFromReaderAt(r io.ReaderAt) io.Reader {
|
||||
return &readerAtReader{
|
||||
r: r,
|
||||
off: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (rar *readerAtReader) Read(p []byte) (n int, err error) {
|
||||
n, err = rar.r.ReadAt(p, rar.off)
|
||||
rar.off += int64(n)
|
||||
return n, err
|
||||
}
|
20
vendor/github.com/containers/ocicrypt/spec/spec.go
generated
vendored
Normal file
20
vendor/github.com/containers/ocicrypt/spec/spec.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
package spec
|
||||
|
||||
const (
|
||||
// MediaTypeLayerEnc is MIME type used for encrypted layers.
|
||||
MediaTypeLayerEnc = "application/vnd.oci.image.layer.v1.tar+encrypted"
|
||||
// MediaTypeLayerGzipEnc is MIME type used for encrypted gzip-compressed layers.
|
||||
MediaTypeLayerGzipEnc = "application/vnd.oci.image.layer.v1.tar+gzip+encrypted"
|
||||
// MediaTypeLayerZstdEnc is MIME type used for encrypted zstd-compressed layers.
|
||||
MediaTypeLayerZstdEnc = "application/vnd.oci.image.layer.v1.tar+zstd+encrypted"
|
||||
// MediaTypeLayerNonDistributableEnc is MIME type used for non distributable encrypted layers.
|
||||
MediaTypeLayerNonDistributableEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+encrypted"
|
||||
// MediaTypeLayerNonDistributableGzipEnc is MIME type used for non distributable encrypted gzip-compressed layers.
|
||||
MediaTypeLayerNonDistributableGzipEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip+encrypted"
|
||||
// MediaTypeLayerNonDistributableZstdEnc is MIME type used for non distributable encrypted zstd-compressed layers.
|
||||
MediaTypeLayerNonDistributableZstdEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+zstd+encrypted"
|
||||
// MediaTypeLayerNonDistributableZsdtEnc is MIME type used for non distributable encrypted zstd-compressed layers.
|
||||
//
|
||||
// Deprecated: Use [MediaTypeLayerNonDistributableZstdEnc].
|
||||
MediaTypeLayerNonDistributableZsdtEnc = MediaTypeLayerNonDistributableZstdEnc
|
||||
)
|
109
vendor/github.com/containers/ocicrypt/utils/delayedreader.go
generated
vendored
Normal file
109
vendor/github.com/containers/ocicrypt/utils/delayedreader.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// DelayedReader wraps a io.Reader and allows a client to use the Reader
|
||||
// interface. The DelayedReader holds back some buffer to the client
|
||||
// so that it can report any error that occurred on the Reader it wraps
|
||||
// early to the client while it may still have held some data back.
|
||||
type DelayedReader struct {
|
||||
reader io.Reader // Reader to Read() bytes from and delay them
|
||||
err error // error that occurred on the reader
|
||||
buffer []byte // delay buffer
|
||||
bufbytes int // number of bytes in the delay buffer to give to Read(); on '0' we return 'EOF' to caller
|
||||
bufoff int // offset in the delay buffer to give to Read()
|
||||
}
|
||||
|
||||
// NewDelayedReader wraps a io.Reader and allocates a delay buffer of bufsize bytes
|
||||
func NewDelayedReader(reader io.Reader, bufsize uint) io.Reader {
|
||||
return &DelayedReader{
|
||||
reader: reader,
|
||||
buffer: make([]byte, bufsize),
|
||||
}
|
||||
}
|
||||
|
||||
// Read implements the io.Reader interface
|
||||
func (dr *DelayedReader) Read(p []byte) (int, error) {
|
||||
if dr.err != nil && dr.err != io.EOF {
|
||||
return 0, dr.err
|
||||
}
|
||||
|
||||
// if we are completely drained, return io.EOF
|
||||
if dr.err == io.EOF && dr.bufbytes == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
// only at the beginning we fill our delay buffer in an extra step
|
||||
if dr.bufbytes < len(dr.buffer) && dr.err == nil {
|
||||
dr.bufbytes, dr.err = FillBuffer(dr.reader, dr.buffer)
|
||||
if dr.err != nil && dr.err != io.EOF {
|
||||
return 0, dr.err
|
||||
}
|
||||
}
|
||||
// dr.err != nil means we have EOF and can drain the delay buffer
|
||||
// otherwise we need to still read from the reader
|
||||
|
||||
var tmpbuf []byte
|
||||
tmpbufbytes := 0
|
||||
if dr.err == nil {
|
||||
tmpbuf = make([]byte, len(p))
|
||||
tmpbufbytes, dr.err = FillBuffer(dr.reader, tmpbuf)
|
||||
if dr.err != nil && dr.err != io.EOF {
|
||||
return 0, dr.err
|
||||
}
|
||||
}
|
||||
|
||||
// copy out of the delay buffer into 'p'
|
||||
tocopy1 := min(len(p), dr.bufbytes)
|
||||
c1 := copy(p[:tocopy1], dr.buffer[dr.bufoff:])
|
||||
dr.bufoff += c1
|
||||
dr.bufbytes -= c1
|
||||
|
||||
c2 := 0
|
||||
// can p still hold more data?
|
||||
if c1 < len(p) {
|
||||
// copy out of the tmpbuf into 'p'
|
||||
c2 = copy(p[tocopy1:], tmpbuf[:tmpbufbytes])
|
||||
}
|
||||
|
||||
// if tmpbuf holds data we need to hold onto, copy them
|
||||
// into the delay buffer
|
||||
if tmpbufbytes-c2 > 0 {
|
||||
// left-shift the delay buffer and append the tmpbuf's remaining data
|
||||
dr.buffer = dr.buffer[dr.bufoff : dr.bufoff+dr.bufbytes]
|
||||
dr.buffer = append(dr.buffer, tmpbuf[c2:tmpbufbytes]...)
|
||||
dr.bufoff = 0
|
||||
dr.bufbytes = len(dr.buffer)
|
||||
}
|
||||
|
||||
var err error
|
||||
if dr.bufbytes == 0 {
|
||||
err = io.EOF
|
||||
}
|
||||
return c1 + c2, err
|
||||
}
|
58
vendor/github.com/containers/ocicrypt/utils/ioutils.go
generated
vendored
Normal file
58
vendor/github.com/containers/ocicrypt/utils/ioutils.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// FillBuffer fills the given buffer with as many bytes from the reader as possible. It returns
|
||||
// EOF if an EOF was encountered or any other error.
|
||||
func FillBuffer(reader io.Reader, buffer []byte) (int, error) {
|
||||
n, err := io.ReadFull(reader, buffer)
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
return n, io.EOF
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// first argument is the command, like cat or echo,
|
||||
// the second is the list of args to pass to it
|
||||
type CommandExecuter interface {
|
||||
Exec(string, []string, []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
type Runner struct{}
|
||||
|
||||
// ExecuteCommand is used to execute a linux command line command and return the output of the command with an error if it exists.
|
||||
func (r Runner) Exec(cmdName string, args []string, input []byte) ([]byte, error) {
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
stdInputBuffer := bytes.NewBuffer(input)
|
||||
cmd := exec.Command(cmdName, args...)
|
||||
cmd.Stdin = stdInputBuffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error while running command: %s. stderr: %s: %w", cmdName, stderr.String(), err)
|
||||
}
|
||||
return out.Bytes(), nil
|
||||
}
|
243
vendor/github.com/containers/ocicrypt/utils/keyprovider/keyprovider.pb.go
generated
vendored
Normal file
243
vendor/github.com/containers/ocicrypt/utils/keyprovider/keyprovider.pb.go
generated
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: keyprovider.proto
|
||||
|
||||
package keyprovider
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type KeyProviderKeyWrapProtocolInput struct {
|
||||
KeyProviderKeyWrapProtocolInput []byte `protobuf:"bytes,1,opt,name=KeyProviderKeyWrapProtocolInput,proto3" json:"KeyProviderKeyWrapProtocolInput,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *KeyProviderKeyWrapProtocolInput) Reset() { *m = KeyProviderKeyWrapProtocolInput{} }
|
||||
func (m *KeyProviderKeyWrapProtocolInput) String() string { return proto.CompactTextString(m) }
|
||||
func (*KeyProviderKeyWrapProtocolInput) ProtoMessage() {}
|
||||
func (*KeyProviderKeyWrapProtocolInput) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_da74c8e785ad390c, []int{0}
|
||||
}
|
||||
|
||||
func (m *KeyProviderKeyWrapProtocolInput) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_KeyProviderKeyWrapProtocolInput.Unmarshal(m, b)
|
||||
}
|
||||
func (m *KeyProviderKeyWrapProtocolInput) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_KeyProviderKeyWrapProtocolInput.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *KeyProviderKeyWrapProtocolInput) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_KeyProviderKeyWrapProtocolInput.Merge(m, src)
|
||||
}
|
||||
func (m *KeyProviderKeyWrapProtocolInput) XXX_Size() int {
|
||||
return xxx_messageInfo_KeyProviderKeyWrapProtocolInput.Size(m)
|
||||
}
|
||||
func (m *KeyProviderKeyWrapProtocolInput) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_KeyProviderKeyWrapProtocolInput.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_KeyProviderKeyWrapProtocolInput proto.InternalMessageInfo
|
||||
|
||||
func (m *KeyProviderKeyWrapProtocolInput) GetKeyProviderKeyWrapProtocolInput() []byte {
|
||||
if m != nil {
|
||||
return m.KeyProviderKeyWrapProtocolInput
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type KeyProviderKeyWrapProtocolOutput struct {
|
||||
KeyProviderKeyWrapProtocolOutput []byte `protobuf:"bytes,1,opt,name=KeyProviderKeyWrapProtocolOutput,proto3" json:"KeyProviderKeyWrapProtocolOutput,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *KeyProviderKeyWrapProtocolOutput) Reset() { *m = KeyProviderKeyWrapProtocolOutput{} }
|
||||
func (m *KeyProviderKeyWrapProtocolOutput) String() string { return proto.CompactTextString(m) }
|
||||
func (*KeyProviderKeyWrapProtocolOutput) ProtoMessage() {}
|
||||
func (*KeyProviderKeyWrapProtocolOutput) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_da74c8e785ad390c, []int{1}
|
||||
}
|
||||
|
||||
func (m *KeyProviderKeyWrapProtocolOutput) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_KeyProviderKeyWrapProtocolOutput.Unmarshal(m, b)
|
||||
}
|
||||
func (m *KeyProviderKeyWrapProtocolOutput) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_KeyProviderKeyWrapProtocolOutput.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *KeyProviderKeyWrapProtocolOutput) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_KeyProviderKeyWrapProtocolOutput.Merge(m, src)
|
||||
}
|
||||
func (m *KeyProviderKeyWrapProtocolOutput) XXX_Size() int {
|
||||
return xxx_messageInfo_KeyProviderKeyWrapProtocolOutput.Size(m)
|
||||
}
|
||||
func (m *KeyProviderKeyWrapProtocolOutput) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_KeyProviderKeyWrapProtocolOutput.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_KeyProviderKeyWrapProtocolOutput proto.InternalMessageInfo
|
||||
|
||||
func (m *KeyProviderKeyWrapProtocolOutput) GetKeyProviderKeyWrapProtocolOutput() []byte {
|
||||
if m != nil {
|
||||
return m.KeyProviderKeyWrapProtocolOutput
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*KeyProviderKeyWrapProtocolInput)(nil), "keyprovider.keyProviderKeyWrapProtocolInput")
|
||||
proto.RegisterType((*KeyProviderKeyWrapProtocolOutput)(nil), "keyprovider.keyProviderKeyWrapProtocolOutput")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("keyprovider.proto", fileDescriptor_da74c8e785ad390c)
|
||||
}
|
||||
|
||||
var fileDescriptor_da74c8e785ad390c = []byte{
|
||||
// 169 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x12, 0xcc, 0x4e, 0xad, 0x2c,
|
||||
0x28, 0xca, 0x2f, 0xcb, 0x4c, 0x49, 0x2d, 0xd2, 0x03, 0x32, 0x4a, 0xf2, 0x85, 0xb8, 0x91, 0x84,
|
||||
0x94, 0xb2, 0xb9, 0xe4, 0x81, 0xdc, 0x00, 0x28, 0xd7, 0x3b, 0xb5, 0x32, 0xbc, 0x28, 0xb1, 0x20,
|
||||
0x00, 0xa4, 0x2e, 0x39, 0x3f, 0xc7, 0x33, 0xaf, 0xa0, 0xb4, 0x44, 0xc8, 0x83, 0x4b, 0xde, 0x1b,
|
||||
0xbf, 0x12, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x9e, 0x20, 0x42, 0xca, 0x94, 0xf2, 0xb8, 0x14, 0x70,
|
||||
0x5b, 0xe6, 0x5f, 0x5a, 0x02, 0xb2, 0xcd, 0x8b, 0x4b, 0xc1, 0x9b, 0x80, 0x1a, 0xa8, 0x75, 0x04,
|
||||
0xd5, 0x19, 0xbd, 0x62, 0xe4, 0x12, 0x42, 0x52, 0x14, 0x9c, 0x5a, 0x54, 0x96, 0x99, 0x9c, 0x2a,
|
||||
0x94, 0xc1, 0xc5, 0x0e, 0x52, 0x0c, 0x94, 0x11, 0xd2, 0xd1, 0x43, 0x0e, 0x1f, 0x02, 0x21, 0x21,
|
||||
0xa5, 0x4b, 0xa4, 0x6a, 0x88, 0xf5, 0x4a, 0x0c, 0x42, 0x59, 0x5c, 0x9c, 0xa1, 0x79, 0xf4, 0xb1,
|
||||
0xcb, 0x89, 0x37, 0x0a, 0x39, 0x62, 0x93, 0xd8, 0xc0, 0x91, 0x6d, 0x0c, 0x08, 0x00, 0x00, 0xff,
|
||||
0xff, 0x9a, 0x10, 0xcb, 0xf9, 0x01, 0x02, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConnInterface
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion6
|
||||
|
||||
// KeyProviderServiceClient is the client API for KeyProviderService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type KeyProviderServiceClient interface {
|
||||
WrapKey(ctx context.Context, in *KeyProviderKeyWrapProtocolInput, opts ...grpc.CallOption) (*KeyProviderKeyWrapProtocolOutput, error)
|
||||
UnWrapKey(ctx context.Context, in *KeyProviderKeyWrapProtocolInput, opts ...grpc.CallOption) (*KeyProviderKeyWrapProtocolOutput, error)
|
||||
}
|
||||
|
||||
type keyProviderServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewKeyProviderServiceClient(cc grpc.ClientConnInterface) KeyProviderServiceClient {
|
||||
return &keyProviderServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *keyProviderServiceClient) WrapKey(ctx context.Context, in *KeyProviderKeyWrapProtocolInput, opts ...grpc.CallOption) (*KeyProviderKeyWrapProtocolOutput, error) {
|
||||
out := new(KeyProviderKeyWrapProtocolOutput)
|
||||
err := c.cc.Invoke(ctx, "/keyprovider.KeyProviderService/WrapKey", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *keyProviderServiceClient) UnWrapKey(ctx context.Context, in *KeyProviderKeyWrapProtocolInput, opts ...grpc.CallOption) (*KeyProviderKeyWrapProtocolOutput, error) {
|
||||
out := new(KeyProviderKeyWrapProtocolOutput)
|
||||
err := c.cc.Invoke(ctx, "/keyprovider.KeyProviderService/UnWrapKey", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// KeyProviderServiceServer is the server API for KeyProviderService service.
|
||||
type KeyProviderServiceServer interface {
|
||||
WrapKey(context.Context, *KeyProviderKeyWrapProtocolInput) (*KeyProviderKeyWrapProtocolOutput, error)
|
||||
UnWrapKey(context.Context, *KeyProviderKeyWrapProtocolInput) (*KeyProviderKeyWrapProtocolOutput, error)
|
||||
}
|
||||
|
||||
// UnimplementedKeyProviderServiceServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedKeyProviderServiceServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedKeyProviderServiceServer) WrapKey(ctx context.Context, req *KeyProviderKeyWrapProtocolInput) (*KeyProviderKeyWrapProtocolOutput, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method WrapKey not implemented")
|
||||
}
|
||||
func (*UnimplementedKeyProviderServiceServer) UnWrapKey(ctx context.Context, req *KeyProviderKeyWrapProtocolInput) (*KeyProviderKeyWrapProtocolOutput, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UnWrapKey not implemented")
|
||||
}
|
||||
|
||||
func RegisterKeyProviderServiceServer(s *grpc.Server, srv KeyProviderServiceServer) {
|
||||
s.RegisterService(&_KeyProviderService_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _KeyProviderService_WrapKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(KeyProviderKeyWrapProtocolInput)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(KeyProviderServiceServer).WrapKey(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/keyprovider.KeyProviderService/WrapKey",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(KeyProviderServiceServer).WrapKey(ctx, req.(*KeyProviderKeyWrapProtocolInput))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _KeyProviderService_UnWrapKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(KeyProviderKeyWrapProtocolInput)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(KeyProviderServiceServer).UnWrapKey(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/keyprovider.KeyProviderService/UnWrapKey",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(KeyProviderServiceServer).UnWrapKey(ctx, req.(*KeyProviderKeyWrapProtocolInput))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _KeyProviderService_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "keyprovider.KeyProviderService",
|
||||
HandlerType: (*KeyProviderServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "WrapKey",
|
||||
Handler: _KeyProviderService_WrapKey_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "UnWrapKey",
|
||||
Handler: _KeyProviderService_UnWrapKey_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "keyprovider.proto",
|
||||
}
|
17
vendor/github.com/containers/ocicrypt/utils/keyprovider/keyprovider.proto
generated
vendored
Normal file
17
vendor/github.com/containers/ocicrypt/utils/keyprovider/keyprovider.proto
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package keyprovider;
|
||||
option go_package = "keyprovider";
|
||||
|
||||
message keyProviderKeyWrapProtocolInput {
|
||||
bytes KeyProviderKeyWrapProtocolInput = 1;
|
||||
}
|
||||
|
||||
message keyProviderKeyWrapProtocolOutput {
|
||||
bytes KeyProviderKeyWrapProtocolOutput = 1;
|
||||
}
|
||||
|
||||
service KeyProviderService {
|
||||
rpc WrapKey(keyProviderKeyWrapProtocolInput) returns (keyProviderKeyWrapProtocolOutput) {};
|
||||
rpc UnWrapKey(keyProviderKeyWrapProtocolInput) returns (keyProviderKeyWrapProtocolOutput) {};
|
||||
}
|
174
vendor/github.com/containers/ocicrypt/utils/testing.go
generated
vendored
Normal file
174
vendor/github.com/containers/ocicrypt/utils/testing.go
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CreateRSAKey creates an RSA key
|
||||
func CreateRSAKey(bits int) (*rsa.PrivateKey, error) {
|
||||
key, err := rsa.GenerateKey(rand.Reader, bits)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("rsa.GenerateKey failed: %w", err)
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// CreateECDSAKey creates an elliptic curve key for the given curve
|
||||
func CreateECDSAKey(curve elliptic.Curve) (*ecdsa.PrivateKey, error) {
|
||||
key, err := ecdsa.GenerateKey(curve, rand.Reader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ecdsa.GenerateKey failed: %w", err)
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// CreateRSATestKey creates an RSA key of the given size and returns
|
||||
// the public and private key in PEM or DER format
|
||||
func CreateRSATestKey(bits int, password []byte, pemencode bool) ([]byte, []byte, error) {
|
||||
key, err := CreateRSAKey(bits)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pubData, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("x509.MarshalPKIXPublicKey failed: %w", err)
|
||||
}
|
||||
privData := x509.MarshalPKCS1PrivateKey(key)
|
||||
|
||||
// no more encoding needed for DER
|
||||
if !pemencode {
|
||||
return pubData, privData, nil
|
||||
}
|
||||
|
||||
publicKey := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "PUBLIC KEY",
|
||||
Bytes: pubData,
|
||||
})
|
||||
|
||||
var block *pem.Block
|
||||
|
||||
typ := "RSA PRIVATE KEY"
|
||||
if len(password) > 0 {
|
||||
block, err = x509.EncryptPEMBlock(rand.Reader, typ, privData, password, x509.PEMCipherAES256) //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("x509.EncryptPEMBlock failed: %w", err)
|
||||
}
|
||||
} else {
|
||||
block = &pem.Block{
|
||||
Type: typ,
|
||||
Bytes: privData,
|
||||
}
|
||||
}
|
||||
|
||||
privateKey := pem.EncodeToMemory(block)
|
||||
|
||||
return publicKey, privateKey, nil
|
||||
}
|
||||
|
||||
// CreateECDSATestKey creates and elliptic curve key for the given curve and returns
|
||||
// the public and private key in DER format
|
||||
func CreateECDSATestKey(curve elliptic.Curve) ([]byte, []byte, error) {
|
||||
key, err := CreateECDSAKey(curve)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pubData, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("x509.MarshalPKIXPublicKey failed: %w", err)
|
||||
}
|
||||
|
||||
privData, err := x509.MarshalECPrivateKey(key)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("x509.MarshalECPrivateKey failed: %w", err)
|
||||
}
|
||||
|
||||
return pubData, privData, nil
|
||||
}
|
||||
|
||||
// CreateTestCA creates a root CA for testing
|
||||
func CreateTestCA() (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("rsa.GenerateKey failed: %w", err)
|
||||
}
|
||||
|
||||
ca := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
CommonName: "test-ca",
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().AddDate(1, 0, 0),
|
||||
IsCA: true,
|
||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
caCert, err := certifyKey(&key.PublicKey, ca, key, ca)
|
||||
|
||||
return key, caCert, err
|
||||
}
|
||||
|
||||
// CertifyKey certifies a public key using the given CA's private key and cert;
|
||||
// The certificate template for the public key is optional
|
||||
func CertifyKey(pubbytes []byte, template *x509.Certificate, caKey *rsa.PrivateKey, caCert *x509.Certificate) (*x509.Certificate, error) {
|
||||
pubKey, err := ParsePublicKey(pubbytes, "CertifyKey")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return certifyKey(pubKey, template, caKey, caCert)
|
||||
}
|
||||
|
||||
func certifyKey(pub interface{}, template *x509.Certificate, caKey *rsa.PrivateKey, caCert *x509.Certificate) (*x509.Certificate, error) {
|
||||
if template == nil {
|
||||
template = &x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
CommonName: "testkey",
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(time.Hour),
|
||||
IsCA: false,
|
||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
}
|
||||
|
||||
certDER, err := x509.CreateCertificate(rand.Reader, template, caCert, pub, caKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("x509.CreateCertificate failed: %w", err)
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(certDER)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("x509.ParseCertificate failed: %w", err)
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
}
|
249
vendor/github.com/containers/ocicrypt/utils/utils.go
generated
vendored
Normal file
249
vendor/github.com/containers/ocicrypt/utils/utils.go
generated
vendored
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
Copyright The ocicrypt Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/ocicrypt/crypto/pkcs11"
|
||||
"github.com/go-jose/go-jose/v3"
|
||||
"golang.org/x/crypto/openpgp"
|
||||
)
|
||||
|
||||
// parseJWKPrivateKey parses the input byte array as a JWK and makes sure it's a private key
|
||||
func parseJWKPrivateKey(privKey []byte, prefix string) (interface{}, error) {
|
||||
jwk := jose.JSONWebKey{}
|
||||
err := jwk.UnmarshalJSON(privKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: Could not parse input as JWK: %w", prefix, err)
|
||||
}
|
||||
if jwk.IsPublic() {
|
||||
return nil, fmt.Errorf("%s: JWK is not a private key", prefix)
|
||||
}
|
||||
return &jwk, nil
|
||||
}
|
||||
|
||||
// parseJWKPublicKey parses the input byte array as a JWK
|
||||
func parseJWKPublicKey(privKey []byte, prefix string) (interface{}, error) {
|
||||
jwk := jose.JSONWebKey{}
|
||||
err := jwk.UnmarshalJSON(privKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: Could not parse input as JWK: %w", prefix, err)
|
||||
}
|
||||
if !jwk.IsPublic() {
|
||||
return nil, fmt.Errorf("%s: JWK is not a public key", prefix)
|
||||
}
|
||||
return &jwk, nil
|
||||
}
|
||||
|
||||
// parsePkcs11PrivateKeyYaml parses the input byte array as pkcs11 key file yaml format)
|
||||
func parsePkcs11PrivateKeyYaml(yaml []byte, prefix string) (*pkcs11.Pkcs11KeyFileObject, error) {
|
||||
// if the URI does not have enough attributes, we will throw an error when decrypting
|
||||
return pkcs11.ParsePkcs11KeyFile(yaml)
|
||||
}
|
||||
|
||||
// parsePkcs11URIPublicKey parses the input byte array as a pkcs11 key file yaml
|
||||
func parsePkcs11PublicKeyYaml(yaml []byte, prefix string) (*pkcs11.Pkcs11KeyFileObject, error) {
|
||||
// if the URI does not have enough attributes, we will throw an error when decrypting
|
||||
return pkcs11.ParsePkcs11KeyFile(yaml)
|
||||
}
|
||||
|
||||
// IsPasswordError checks whether an error is related to a missing or wrong
|
||||
// password
|
||||
func IsPasswordError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
msg := strings.ToLower(err.Error())
|
||||
|
||||
return strings.Contains(msg, "password") &&
|
||||
(strings.Contains(msg, "missing") || strings.Contains(msg, "wrong"))
|
||||
}
|
||||
|
||||
// ParsePrivateKey tries to parse a private key in DER format first and
|
||||
// PEM format after, returning an error if the parsing failed
|
||||
func ParsePrivateKey(privKey, privKeyPassword []byte, prefix string) (interface{}, error) {
|
||||
key, err := x509.ParsePKCS8PrivateKey(privKey)
|
||||
if err != nil {
|
||||
key, err = x509.ParsePKCS1PrivateKey(privKey)
|
||||
if err != nil {
|
||||
key, err = x509.ParseECPrivateKey(privKey)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
block, _ := pem.Decode(privKey)
|
||||
if block != nil {
|
||||
var der []byte
|
||||
if x509.IsEncryptedPEMBlock(block) { //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility
|
||||
if privKeyPassword == nil {
|
||||
return nil, fmt.Errorf("%s: Missing password for encrypted private key", prefix)
|
||||
}
|
||||
der, err = x509.DecryptPEMBlock(block, privKeyPassword) //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: Wrong password: could not decrypt private key", prefix)
|
||||
}
|
||||
} else {
|
||||
der = block.Bytes
|
||||
}
|
||||
|
||||
key, err = x509.ParsePKCS8PrivateKey(der)
|
||||
if err != nil {
|
||||
key, err = x509.ParsePKCS1PrivateKey(der)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: Could not parse private key: %w", prefix, err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
key, err = parseJWKPrivateKey(privKey, prefix)
|
||||
if err != nil {
|
||||
key, err = parsePkcs11PrivateKeyYaml(privKey, prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
return key, err
|
||||
}
|
||||
|
||||
// IsPrivateKey returns true in case the given byte array represents a private key
|
||||
// It returns an error if for example the password is wrong
|
||||
func IsPrivateKey(data []byte, password []byte) (bool, error) {
|
||||
_, err := ParsePrivateKey(data, password, "")
|
||||
return err == nil, err
|
||||
}
|
||||
|
||||
// IsPkcs11PrivateKey returns true in case the given byte array represents a pkcs11 private key
|
||||
func IsPkcs11PrivateKey(data []byte) bool {
|
||||
return pkcs11.IsPkcs11PrivateKey(data)
|
||||
}
|
||||
|
||||
// ParsePublicKey tries to parse a public key in DER format first and
|
||||
// PEM format after, returning an error if the parsing failed
|
||||
func ParsePublicKey(pubKey []byte, prefix string) (interface{}, error) {
|
||||
key, err := x509.ParsePKIXPublicKey(pubKey)
|
||||
if err != nil {
|
||||
block, _ := pem.Decode(pubKey)
|
||||
if block != nil {
|
||||
key, err = x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: Could not parse public key: %w", prefix, err)
|
||||
}
|
||||
} else {
|
||||
key, err = parseJWKPublicKey(pubKey, prefix)
|
||||
if err != nil {
|
||||
key, err = parsePkcs11PublicKeyYaml(pubKey, prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
return key, err
|
||||
}
|
||||
|
||||
// IsPublicKey returns true in case the given byte array represents a public key
|
||||
func IsPublicKey(data []byte) bool {
|
||||
_, err := ParsePublicKey(data, "")
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsPkcs11PublicKey returns true in case the given byte array represents a pkcs11 public key
|
||||
func IsPkcs11PublicKey(data []byte) bool {
|
||||
return pkcs11.IsPkcs11PublicKey(data)
|
||||
}
|
||||
|
||||
// ParseCertificate tries to parse a public key in DER format first and
|
||||
// PEM format after, returning an error if the parsing failed
|
||||
func ParseCertificate(certBytes []byte, prefix string) (*x509.Certificate, error) {
|
||||
x509Cert, err := x509.ParseCertificate(certBytes)
|
||||
if err != nil {
|
||||
block, _ := pem.Decode(certBytes)
|
||||
if block == nil {
|
||||
return nil, fmt.Errorf("%s: Could not PEM decode x509 certificate", prefix)
|
||||
}
|
||||
x509Cert, err = x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: Could not parse x509 certificate: %w", prefix, err)
|
||||
}
|
||||
}
|
||||
return x509Cert, err
|
||||
}
|
||||
|
||||
// IsCertificate returns true in case the given byte array represents an x.509 certificate
|
||||
func IsCertificate(data []byte) bool {
|
||||
_, err := ParseCertificate(data, "")
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsGPGPrivateKeyRing returns true in case the given byte array represents a GPG private key ring file
|
||||
func IsGPGPrivateKeyRing(data []byte) bool {
|
||||
r := bytes.NewBuffer(data)
|
||||
_, err := openpgp.ReadKeyRing(r)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// SortDecryptionKeys parses a list of comma separated base64 entries and sorts the data into
|
||||
// a map. Each entry in the list may be either a GPG private key ring, private key, or x.509
|
||||
// certificate
|
||||
func SortDecryptionKeys(b64ItemList string) (map[string][][]byte, error) {
|
||||
dcparameters := make(map[string][][]byte)
|
||||
|
||||
for _, b64Item := range strings.Split(b64ItemList, ",") {
|
||||
var password []byte
|
||||
b64Data := strings.Split(b64Item, ":")
|
||||
keyData, err := base64.StdEncoding.DecodeString(b64Data[0])
|
||||
if err != nil {
|
||||
return nil, errors.New("Could not base64 decode a passed decryption key")
|
||||
}
|
||||
if len(b64Data) == 2 {
|
||||
password, err = base64.StdEncoding.DecodeString(b64Data[1])
|
||||
if err != nil {
|
||||
return nil, errors.New("Could not base64 decode a passed decryption key password")
|
||||
}
|
||||
}
|
||||
var key string
|
||||
isPrivKey, err := IsPrivateKey(keyData, password)
|
||||
if IsPasswordError(err) {
|
||||
return nil, err
|
||||
}
|
||||
if isPrivKey {
|
||||
key = "privkeys"
|
||||
if _, ok := dcparameters["privkeys-passwords"]; !ok {
|
||||
dcparameters["privkeys-passwords"] = [][]byte{password}
|
||||
} else {
|
||||
dcparameters["privkeys-passwords"] = append(dcparameters["privkeys-passwords"], password)
|
||||
}
|
||||
} else if IsCertificate(keyData) {
|
||||
key = "x509s"
|
||||
} else if IsGPGPrivateKeyRing(keyData) {
|
||||
key = "gpg-privatekeys"
|
||||
}
|
||||
if key != "" {
|
||||
values := dcparameters[key]
|
||||
if values == nil {
|
||||
dcparameters[key] = [][]byte{keyData}
|
||||
} else {
|
||||
dcparameters[key] = append(dcparameters[key], keyData)
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("Unknown decryption key type")
|
||||
}
|
||||
}
|
||||
|
||||
return dcparameters, nil
|
||||
}
|
2
vendor/github.com/go-jose/go-jose/v3/.gitignore
generated
vendored
Normal file
2
vendor/github.com/go-jose/go-jose/v3/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
jose-util/jose-util
|
||||
jose-util.t.err
|
53
vendor/github.com/go-jose/go-jose/v3/.golangci.yml
generated
vendored
Normal file
53
vendor/github.com/go-jose/go-jose/v3/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
# https://github.com/golangci/golangci-lint
|
||||
|
||||
run:
|
||||
skip-files:
|
||||
- doc_test.go
|
||||
modules-download-mode: readonly
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- gochecknoglobals
|
||||
- goconst
|
||||
- lll
|
||||
- maligned
|
||||
- nakedret
|
||||
- scopelint
|
||||
- unparam
|
||||
- funlen # added in 1.18 (requires go-jose changes before it can be enabled)
|
||||
|
||||
linters-settings:
|
||||
gocyclo:
|
||||
min-complexity: 35
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
- text: "don't use ALL_CAPS in Go names"
|
||||
linters:
|
||||
- golint
|
||||
- text: "hardcoded credentials"
|
||||
linters:
|
||||
- gosec
|
||||
- text: "weak cryptographic primitive"
|
||||
linters:
|
||||
- gosec
|
||||
- path: json/
|
||||
linters:
|
||||
- dupl
|
||||
- errcheck
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- golint
|
||||
- govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- stylecheck
|
||||
- unused
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- scopelint
|
||||
- path: jwk.go
|
||||
linters:
|
||||
- gocyclo
|
33
vendor/github.com/go-jose/go-jose/v3/.travis.yml
generated
vendored
Normal file
33
vendor/github.com/go-jose/go-jose/v3/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
language: go
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
go:
|
||||
- "1.13.x"
|
||||
- "1.14.x"
|
||||
- tip
|
||||
|
||||
before_script:
|
||||
- export PATH=$HOME/.local/bin:$PATH
|
||||
|
||||
before_install:
|
||||
- go get -u github.com/mattn/goveralls github.com/wadey/gocovmerge
|
||||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.18.0
|
||||
- pip install cram --user
|
||||
|
||||
script:
|
||||
- go test -v -covermode=count -coverprofile=profile.cov .
|
||||
- go test -v -covermode=count -coverprofile=cryptosigner/profile.cov ./cryptosigner
|
||||
- go test -v -covermode=count -coverprofile=cipher/profile.cov ./cipher
|
||||
- go test -v -covermode=count -coverprofile=jwt/profile.cov ./jwt
|
||||
- go test -v ./json # no coverage for forked encoding/json package
|
||||
- golangci-lint run
|
||||
- cd jose-util && go build && PATH=$PWD:$PATH cram -v jose-util.t # cram tests jose-util
|
||||
- cd ..
|
||||
|
||||
after_success:
|
||||
- gocovmerge *.cov */*.cov > merged.coverprofile
|
||||
- goveralls -coverprofile merged.coverprofile -service=travis-ci
|
78
vendor/github.com/go-jose/go-jose/v3/CHANGELOG.md
generated
vendored
Normal file
78
vendor/github.com/go-jose/go-jose/v3/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
# v4.0.1
|
||||
|
||||
## Fixed
|
||||
|
||||
- An attacker could send a JWE containing compressed data that used large
|
||||
amounts of memory and CPU when decompressed by `Decrypt` or `DecryptMulti`.
|
||||
Those functions now return an error if the decompressed data would exceed
|
||||
250kB or 10x the compressed size (whichever is larger). Thanks to
|
||||
Enze Wang@Alioth and Jianjun Chen@Zhongguancun Lab (@zer0yu and @chenjj)
|
||||
for reporting.
|
||||
|
||||
# v4.0.0
|
||||
|
||||
This release makes some breaking changes in order to more thoroughly
|
||||
address the vulnerabilities discussed in [Three New Attacks Against JSON Web
|
||||
Tokens][1], "Sign/encrypt confusion", "Billion hash attack", and "Polyglot
|
||||
token".
|
||||
|
||||
## Changed
|
||||
|
||||
- Limit JWT encryption types (exclude password or public key types) (#78)
|
||||
- Enforce minimum length for HMAC keys (#85)
|
||||
- jwt: match any audience in a list, rather than requiring all audiences (#81)
|
||||
- jwt: accept only Compact Serialization (#75)
|
||||
- jws: Add expected algorithms for signatures (#74)
|
||||
- Require specifying expected algorithms for ParseEncrypted,
|
||||
ParseSigned, ParseDetached, jwt.ParseEncrypted, jwt.ParseSigned,
|
||||
jwt.ParseSignedAndEncrypted (#69, #74)
|
||||
- Usually there is a small, known set of appropriate algorithms for a program
|
||||
to use and it's a mistake to allow unexpected algorithms. For instance the
|
||||
"billion hash attack" relies in part on programs accepting the PBES2
|
||||
encryption algorithm and doing the necessary work even if they weren't
|
||||
specifically configured to allow PBES2.
|
||||
- Revert "Strip padding off base64 strings" (#82)
|
||||
- The specs require base64url encoding without padding.
|
||||
- Minimum supported Go version is now 1.21
|
||||
|
||||
## Added
|
||||
|
||||
- ParseSignedCompact, ParseSignedJSON, ParseEncryptedCompact, ParseEncryptedJSON.
|
||||
- These allow parsing a specific serialization, as opposed to ParseSigned and
|
||||
ParseEncrypted, which try to automatically detect which serialization was
|
||||
provided. It's common to require a specific serialization for a specific
|
||||
protocol - for instance JWT requires Compact serialization.
|
||||
|
||||
[1]: https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
|
||||
|
||||
# v3.0.3
|
||||
|
||||
## Fixed
|
||||
|
||||
- Limit decompression output size to prevent a DoS. Backport from v4.0.1.
|
||||
|
||||
# v3.0.2
|
||||
|
||||
## Fixed
|
||||
|
||||
- DecryptMulti: handle decompression error (#19)
|
||||
|
||||
## Changed
|
||||
|
||||
- jwe/CompactSerialize: improve performance (#67)
|
||||
- Increase the default number of PBKDF2 iterations to 600k (#48)
|
||||
- Return the proper algorithm for ECDSA keys (#45)
|
||||
|
||||
## Added
|
||||
|
||||
- Add Thumbprint support for opaque signers (#38)
|
||||
|
||||
# v3.0.1
|
||||
|
||||
## Fixed
|
||||
|
||||
- Security issue: an attacker specifying a large "p2c" value can cause
|
||||
JSONWebEncryption.Decrypt and JSONWebEncryption.DecryptMulti to consume large
|
||||
amounts of CPU, causing a DoS. Thanks to Matt Schwager (@mschwager) for the
|
||||
disclosure and to Tom Tervoort for originally publishing the category of attack.
|
||||
https://i.blackhat.com/BH-US-23/Presentations/US-23-Tervoort-Three-New-Attacks-Against-JSON-Web-Tokens.pdf
|
15
vendor/github.com/go-jose/go-jose/v3/CONTRIBUTING.md
generated
vendored
Normal file
15
vendor/github.com/go-jose/go-jose/v3/CONTRIBUTING.md
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Contributing
|
||||
|
||||
If you would like to contribute code to go-jose you can do so through GitHub by
|
||||
forking the repository and sending a pull request.
|
||||
|
||||
When submitting code, please make every effort to follow existing conventions
|
||||
and style in order to keep the code as readable as possible. Please also make
|
||||
sure all tests pass by running `go test`, and format your code with `go fmt`.
|
||||
We also recommend using `golint` and `errcheck`.
|
||||
|
||||
Before your code can be accepted into the project you must also sign the
|
||||
Individual Contributor License Agreement. We use [cla-assistant.io][1] and you
|
||||
will be prompted to sign once a pull request is opened.
|
||||
|
||||
[1]: https://cla-assistant.io/
|
202
vendor/github.com/go-jose/go-jose/v3/LICENSE
generated
vendored
Normal file
202
vendor/github.com/go-jose/go-jose/v3/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
108
vendor/github.com/go-jose/go-jose/v3/README.md
generated
vendored
Normal file
108
vendor/github.com/go-jose/go-jose/v3/README.md
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
# Go JOSE
|
||||
|
||||
### Versions
|
||||
|
||||
[Version 4](https://github.com/go-jose/go-jose)
|
||||
([branch](https://github.com/go-jose/go-jose/),
|
||||
[doc](https://pkg.go.dev/github.com/go-jose/go-jose/v4), [releases](https://github.com/go-jose/go-jose/releases)) is the current stable version:
|
||||
|
||||
import "github.com/go-jose/go-jose/v4"
|
||||
|
||||
The old [square/go-jose](https://github.com/square/go-jose) repo contains the prior v1 and v2 versions, which
|
||||
are deprecated.
|
||||
|
||||
### Summary
|
||||
|
||||
Package jose aims to provide an implementation of the Javascript Object Signing
|
||||
and Encryption set of standards. This includes support for JSON Web Encryption,
|
||||
JSON Web Signature, and JSON Web Token standards.
|
||||
|
||||
**Disclaimer**: This library contains encryption software that is subject to
|
||||
the U.S. Export Administration Regulations. You may not export, re-export,
|
||||
transfer or download this code or any part of it in violation of any United
|
||||
States law, directive or regulation. In particular this software may not be
|
||||
exported or re-exported in any form or on any media to Iran, North Sudan,
|
||||
Syria, Cuba, or North Korea, or to denied persons or entities mentioned on any
|
||||
US maintained blocked list.
|
||||
|
||||
## Overview
|
||||
|
||||
The implementation follows the
|
||||
[JSON Web Encryption](https://dx.doi.org/10.17487/RFC7516) (RFC 7516),
|
||||
[JSON Web Signature](https://dx.doi.org/10.17487/RFC7515) (RFC 7515), and
|
||||
[JSON Web Token](https://dx.doi.org/10.17487/RFC7519) (RFC 7519) specifications.
|
||||
Tables of supported algorithms are shown below. The library supports both
|
||||
the compact and JWS/JWE JSON Serialization formats, and has optional support for
|
||||
multiple recipients. It also comes with a small command-line utility
|
||||
([`jose-util`](https://pkg.go.dev/github.com/go-jose/go-jose/jose-util))
|
||||
for dealing with JOSE messages in a shell.
|
||||
|
||||
**Note**: We use a forked version of the `encoding/json` package from the Go
|
||||
standard library which uses case-sensitive matching for member names (instead
|
||||
of [case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html)).
|
||||
This is to avoid differences in interpretation of messages between go-jose and
|
||||
libraries in other languages.
|
||||
|
||||
### Supported algorithms
|
||||
|
||||
See below for a table of supported algorithms. Algorithm identifiers match
|
||||
the names in the [JSON Web Algorithms](https://dx.doi.org/10.17487/RFC7518)
|
||||
standard where possible. The Godoc reference has a list of constants.
|
||||
|
||||
Key encryption | Algorithm identifier(s)
|
||||
:------------------------- | :------------------------------
|
||||
RSA-PKCS#1v1.5 | RSA1_5
|
||||
RSA-OAEP | RSA-OAEP, RSA-OAEP-256
|
||||
AES key wrap | A128KW, A192KW, A256KW
|
||||
AES-GCM key wrap | A128GCMKW, A192GCMKW, A256GCMKW
|
||||
ECDH-ES + AES key wrap | ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW
|
||||
ECDH-ES (direct) | ECDH-ES<sup>1</sup>
|
||||
Direct encryption | dir<sup>1</sup>
|
||||
|
||||
<sup>1. Not supported in multi-recipient mode</sup>
|
||||
|
||||
Signing / MAC | Algorithm identifier(s)
|
||||
:------------------------- | :------------------------------
|
||||
RSASSA-PKCS#1v1.5 | RS256, RS384, RS512
|
||||
RSASSA-PSS | PS256, PS384, PS512
|
||||
HMAC | HS256, HS384, HS512
|
||||
ECDSA | ES256, ES384, ES512
|
||||
Ed25519 | EdDSA<sup>2</sup>
|
||||
|
||||
<sup>2. Only available in version 2 of the package</sup>
|
||||
|
||||
Content encryption | Algorithm identifier(s)
|
||||
:------------------------- | :------------------------------
|
||||
AES-CBC+HMAC | A128CBC-HS256, A192CBC-HS384, A256CBC-HS512
|
||||
AES-GCM | A128GCM, A192GCM, A256GCM
|
||||
|
||||
Compression | Algorithm identifiers(s)
|
||||
:------------------------- | -------------------------------
|
||||
DEFLATE (RFC 1951) | DEF
|
||||
|
||||
### Supported key types
|
||||
|
||||
See below for a table of supported key types. These are understood by the
|
||||
library, and can be passed to corresponding functions such as `NewEncrypter` or
|
||||
`NewSigner`. Each of these keys can also be wrapped in a JWK if desired, which
|
||||
allows attaching a key id.
|
||||
|
||||
Algorithm(s) | Corresponding types
|
||||
:------------------------- | -------------------------------
|
||||
RSA | *[rsa.PublicKey](https://pkg.go.dev/crypto/rsa/#PublicKey), *[rsa.PrivateKey](https://pkg.go.dev/crypto/rsa/#PrivateKey)
|
||||
ECDH, ECDSA | *[ecdsa.PublicKey](https://pkg.go.dev/crypto/ecdsa/#PublicKey), *[ecdsa.PrivateKey](https://pkg.go.dev/crypto/ecdsa/#PrivateKey)
|
||||
EdDSA<sup>1</sup> | [ed25519.PublicKey](https://pkg.go.dev/crypto/ed25519#PublicKey), [ed25519.PrivateKey](https://pkg.go.dev/crypto/ed25519#PrivateKey)
|
||||
AES, HMAC | []byte
|
||||
|
||||
<sup>1. Only available in version 2 or later of the package</sup>
|
||||
|
||||
## Examples
|
||||
|
||||
[](https://pkg.go.dev/github.com/go-jose/go-jose/v3)
|
||||
[](https://pkg.go.dev/github.com/go-jose/go-jose/v3/jwt)
|
||||
|
||||
Examples can be found in the Godoc
|
||||
reference for this package. The
|
||||
[`jose-util`](https://github.com/go-jose/go-jose/tree/v3/jose-util)
|
||||
subdirectory also contains a small command-line utility which might be useful
|
||||
as an example as well.
|
13
vendor/github.com/go-jose/go-jose/v3/SECURITY.md
generated
vendored
Normal file
13
vendor/github.com/go-jose/go-jose/v3/SECURITY.md
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Security Policy
|
||||
This document explains how to contact the Let's Encrypt security team to report security vulnerabilities.
|
||||
|
||||
## Supported Versions
|
||||
| Version | Supported |
|
||||
| ------- | ----------|
|
||||
| >= v3 | ✓ |
|
||||
| v2 | ✗ |
|
||||
| v1 | ✗ |
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
Please see [https://letsencrypt.org/contact/#security](https://letsencrypt.org/contact/#security) for the email address to report a vulnerability. Ensure that the subject line for your report contains the word `vulnerability` and is descriptive. Your email should be acknowledged within 24 hours. If you do not receive a response within 24 hours, please follow-up again with another email.
|
595
vendor/github.com/go-jose/go-jose/v3/asymmetric.go
generated
vendored
Normal file
595
vendor/github.com/go-jose/go-jose/v3/asymmetric.go
generated
vendored
Normal file
@ -0,0 +1,595 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
josecipher "github.com/go-jose/go-jose/v3/cipher"
|
||||
"github.com/go-jose/go-jose/v3/json"
|
||||
)
|
||||
|
||||
// A generic RSA-based encrypter/verifier
|
||||
type rsaEncrypterVerifier struct {
|
||||
publicKey *rsa.PublicKey
|
||||
}
|
||||
|
||||
// A generic RSA-based decrypter/signer
|
||||
type rsaDecrypterSigner struct {
|
||||
privateKey *rsa.PrivateKey
|
||||
}
|
||||
|
||||
// A generic EC-based encrypter/verifier
|
||||
type ecEncrypterVerifier struct {
|
||||
publicKey *ecdsa.PublicKey
|
||||
}
|
||||
|
||||
type edEncrypterVerifier struct {
|
||||
publicKey ed25519.PublicKey
|
||||
}
|
||||
|
||||
// A key generator for ECDH-ES
|
||||
type ecKeyGenerator struct {
|
||||
size int
|
||||
algID string
|
||||
publicKey *ecdsa.PublicKey
|
||||
}
|
||||
|
||||
// A generic EC-based decrypter/signer
|
||||
type ecDecrypterSigner struct {
|
||||
privateKey *ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
type edDecrypterSigner struct {
|
||||
privateKey ed25519.PrivateKey
|
||||
}
|
||||
|
||||
// newRSARecipient creates recipientKeyInfo based on the given key.
|
||||
func newRSARecipient(keyAlg KeyAlgorithm, publicKey *rsa.PublicKey) (recipientKeyInfo, error) {
|
||||
// Verify that key management algorithm is supported by this encrypter
|
||||
switch keyAlg {
|
||||
case RSA1_5, RSA_OAEP, RSA_OAEP_256:
|
||||
default:
|
||||
return recipientKeyInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if publicKey == nil {
|
||||
return recipientKeyInfo{}, errors.New("invalid public key")
|
||||
}
|
||||
|
||||
return recipientKeyInfo{
|
||||
keyAlg: keyAlg,
|
||||
keyEncrypter: &rsaEncrypterVerifier{
|
||||
publicKey: publicKey,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// newRSASigner creates a recipientSigInfo based on the given key.
|
||||
func newRSASigner(sigAlg SignatureAlgorithm, privateKey *rsa.PrivateKey) (recipientSigInfo, error) {
|
||||
// Verify that key management algorithm is supported by this encrypter
|
||||
switch sigAlg {
|
||||
case RS256, RS384, RS512, PS256, PS384, PS512:
|
||||
default:
|
||||
return recipientSigInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if privateKey == nil {
|
||||
return recipientSigInfo{}, errors.New("invalid private key")
|
||||
}
|
||||
|
||||
return recipientSigInfo{
|
||||
sigAlg: sigAlg,
|
||||
publicKey: staticPublicKey(&JSONWebKey{
|
||||
Key: privateKey.Public(),
|
||||
}),
|
||||
signer: &rsaDecrypterSigner{
|
||||
privateKey: privateKey,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newEd25519Signer(sigAlg SignatureAlgorithm, privateKey ed25519.PrivateKey) (recipientSigInfo, error) {
|
||||
if sigAlg != EdDSA {
|
||||
return recipientSigInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if privateKey == nil {
|
||||
return recipientSigInfo{}, errors.New("invalid private key")
|
||||
}
|
||||
return recipientSigInfo{
|
||||
sigAlg: sigAlg,
|
||||
publicKey: staticPublicKey(&JSONWebKey{
|
||||
Key: privateKey.Public(),
|
||||
}),
|
||||
signer: &edDecrypterSigner{
|
||||
privateKey: privateKey,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// newECDHRecipient creates recipientKeyInfo based on the given key.
|
||||
func newECDHRecipient(keyAlg KeyAlgorithm, publicKey *ecdsa.PublicKey) (recipientKeyInfo, error) {
|
||||
// Verify that key management algorithm is supported by this encrypter
|
||||
switch keyAlg {
|
||||
case ECDH_ES, ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW:
|
||||
default:
|
||||
return recipientKeyInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if publicKey == nil || !publicKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
|
||||
return recipientKeyInfo{}, errors.New("invalid public key")
|
||||
}
|
||||
|
||||
return recipientKeyInfo{
|
||||
keyAlg: keyAlg,
|
||||
keyEncrypter: &ecEncrypterVerifier{
|
||||
publicKey: publicKey,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// newECDSASigner creates a recipientSigInfo based on the given key.
|
||||
func newECDSASigner(sigAlg SignatureAlgorithm, privateKey *ecdsa.PrivateKey) (recipientSigInfo, error) {
|
||||
// Verify that key management algorithm is supported by this encrypter
|
||||
switch sigAlg {
|
||||
case ES256, ES384, ES512:
|
||||
default:
|
||||
return recipientSigInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if privateKey == nil {
|
||||
return recipientSigInfo{}, errors.New("invalid private key")
|
||||
}
|
||||
|
||||
return recipientSigInfo{
|
||||
sigAlg: sigAlg,
|
||||
publicKey: staticPublicKey(&JSONWebKey{
|
||||
Key: privateKey.Public(),
|
||||
}),
|
||||
signer: &ecDecrypterSigner{
|
||||
privateKey: privateKey,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Encrypt the given payload and update the object.
|
||||
func (ctx rsaEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
|
||||
encryptedKey, err := ctx.encrypt(cek, alg)
|
||||
if err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
return recipientInfo{
|
||||
encryptedKey: encryptedKey,
|
||||
header: &rawHeader{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Encrypt the given payload. Based on the key encryption algorithm,
|
||||
// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256).
|
||||
func (ctx rsaEncrypterVerifier) encrypt(cek []byte, alg KeyAlgorithm) ([]byte, error) {
|
||||
switch alg {
|
||||
case RSA1_5:
|
||||
return rsa.EncryptPKCS1v15(RandReader, ctx.publicKey, cek)
|
||||
case RSA_OAEP:
|
||||
return rsa.EncryptOAEP(sha1.New(), RandReader, ctx.publicKey, cek, []byte{})
|
||||
case RSA_OAEP_256:
|
||||
return rsa.EncryptOAEP(sha256.New(), RandReader, ctx.publicKey, cek, []byte{})
|
||||
}
|
||||
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
// Decrypt the given payload and return the content encryption key.
|
||||
func (ctx rsaDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
||||
return ctx.decrypt(recipient.encryptedKey, headers.getAlgorithm(), generator)
|
||||
}
|
||||
|
||||
// Decrypt the given payload. Based on the key encryption algorithm,
|
||||
// this will either use RSA-PKCS1v1.5 or RSA-OAEP (with SHA-1 or SHA-256).
|
||||
func (ctx rsaDecrypterSigner) decrypt(jek []byte, alg KeyAlgorithm, generator keyGenerator) ([]byte, error) {
|
||||
// Note: The random reader on decrypt operations is only used for blinding,
|
||||
// so stubbing is meanlingless (hence the direct use of rand.Reader).
|
||||
switch alg {
|
||||
case RSA1_5:
|
||||
defer func() {
|
||||
// DecryptPKCS1v15SessionKey sometimes panics on an invalid payload
|
||||
// because of an index out of bounds error, which we want to ignore.
|
||||
// This has been fixed in Go 1.3.1 (released 2014/08/13), the recover()
|
||||
// only exists for preventing crashes with unpatched versions.
|
||||
// See: https://groups.google.com/forum/#!topic/golang-dev/7ihX6Y6kx9k
|
||||
// See: https://code.google.com/p/go/source/detail?r=58ee390ff31602edb66af41ed10901ec95904d33
|
||||
_ = recover()
|
||||
}()
|
||||
|
||||
// Perform some input validation.
|
||||
keyBytes := ctx.privateKey.PublicKey.N.BitLen() / 8
|
||||
if keyBytes != len(jek) {
|
||||
// Input size is incorrect, the encrypted payload should always match
|
||||
// the size of the public modulus (e.g. using a 2048 bit key will
|
||||
// produce 256 bytes of output). Reject this since it's invalid input.
|
||||
return nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
cek, _, err := generator.genKey()
|
||||
if err != nil {
|
||||
return nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
// When decrypting an RSA-PKCS1v1.5 payload, we must take precautions to
|
||||
// prevent chosen-ciphertext attacks as described in RFC 3218, "Preventing
|
||||
// the Million Message Attack on Cryptographic Message Syntax". We are
|
||||
// therefore deliberately ignoring errors here.
|
||||
_ = rsa.DecryptPKCS1v15SessionKey(rand.Reader, ctx.privateKey, jek, cek)
|
||||
|
||||
return cek, nil
|
||||
case RSA_OAEP:
|
||||
// Use rand.Reader for RSA blinding
|
||||
return rsa.DecryptOAEP(sha1.New(), rand.Reader, ctx.privateKey, jek, []byte{})
|
||||
case RSA_OAEP_256:
|
||||
// Use rand.Reader for RSA blinding
|
||||
return rsa.DecryptOAEP(sha256.New(), rand.Reader, ctx.privateKey, jek, []byte{})
|
||||
}
|
||||
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
// Sign the given payload
|
||||
func (ctx rsaDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
||||
var hash crypto.Hash
|
||||
|
||||
switch alg {
|
||||
case RS256, PS256:
|
||||
hash = crypto.SHA256
|
||||
case RS384, PS384:
|
||||
hash = crypto.SHA384
|
||||
case RS512, PS512:
|
||||
hash = crypto.SHA512
|
||||
default:
|
||||
return Signature{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
hasher := hash.New()
|
||||
|
||||
// According to documentation, Write() on hash never fails
|
||||
_, _ = hasher.Write(payload)
|
||||
hashed := hasher.Sum(nil)
|
||||
|
||||
var out []byte
|
||||
var err error
|
||||
|
||||
switch alg {
|
||||
case RS256, RS384, RS512:
|
||||
// TODO(https://github.com/go-jose/go-jose/issues/40): As of go1.20, the
|
||||
// random parameter is legacy and ignored, and it can be nil.
|
||||
// https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/rsa/pkcs1v15.go;l=263;bpv=0;bpt=1
|
||||
out, err = rsa.SignPKCS1v15(RandReader, ctx.privateKey, hash, hashed)
|
||||
case PS256, PS384, PS512:
|
||||
out, err = rsa.SignPSS(RandReader, ctx.privateKey, hash, hashed, &rsa.PSSOptions{
|
||||
SaltLength: rsa.PSSSaltLengthEqualsHash,
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return Signature{}, err
|
||||
}
|
||||
|
||||
return Signature{
|
||||
Signature: out,
|
||||
protected: &rawHeader{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Verify the given payload
|
||||
func (ctx rsaEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
|
||||
var hash crypto.Hash
|
||||
|
||||
switch alg {
|
||||
case RS256, PS256:
|
||||
hash = crypto.SHA256
|
||||
case RS384, PS384:
|
||||
hash = crypto.SHA384
|
||||
case RS512, PS512:
|
||||
hash = crypto.SHA512
|
||||
default:
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
hasher := hash.New()
|
||||
|
||||
// According to documentation, Write() on hash never fails
|
||||
_, _ = hasher.Write(payload)
|
||||
hashed := hasher.Sum(nil)
|
||||
|
||||
switch alg {
|
||||
case RS256, RS384, RS512:
|
||||
return rsa.VerifyPKCS1v15(ctx.publicKey, hash, hashed, signature)
|
||||
case PS256, PS384, PS512:
|
||||
return rsa.VerifyPSS(ctx.publicKey, hash, hashed, signature, nil)
|
||||
}
|
||||
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
// Encrypt the given payload and update the object.
|
||||
func (ctx ecEncrypterVerifier) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
|
||||
switch alg {
|
||||
case ECDH_ES:
|
||||
// ECDH-ES mode doesn't wrap a key, the shared secret is used directly as the key.
|
||||
return recipientInfo{
|
||||
header: &rawHeader{},
|
||||
}, nil
|
||||
case ECDH_ES_A128KW, ECDH_ES_A192KW, ECDH_ES_A256KW:
|
||||
default:
|
||||
return recipientInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
generator := ecKeyGenerator{
|
||||
algID: string(alg),
|
||||
publicKey: ctx.publicKey,
|
||||
}
|
||||
|
||||
switch alg {
|
||||
case ECDH_ES_A128KW:
|
||||
generator.size = 16
|
||||
case ECDH_ES_A192KW:
|
||||
generator.size = 24
|
||||
case ECDH_ES_A256KW:
|
||||
generator.size = 32
|
||||
}
|
||||
|
||||
kek, header, err := generator.genKey()
|
||||
if err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(kek)
|
||||
if err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
jek, err := josecipher.KeyWrap(block, cek)
|
||||
if err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
return recipientInfo{
|
||||
encryptedKey: jek,
|
||||
header: &header,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Get key size for EC key generator
|
||||
func (ctx ecKeyGenerator) keySize() int {
|
||||
return ctx.size
|
||||
}
|
||||
|
||||
// Get a content encryption key for ECDH-ES
|
||||
func (ctx ecKeyGenerator) genKey() ([]byte, rawHeader, error) {
|
||||
priv, err := ecdsa.GenerateKey(ctx.publicKey.Curve, RandReader)
|
||||
if err != nil {
|
||||
return nil, rawHeader{}, err
|
||||
}
|
||||
|
||||
out := josecipher.DeriveECDHES(ctx.algID, []byte{}, []byte{}, priv, ctx.publicKey, ctx.size)
|
||||
|
||||
b, err := json.Marshal(&JSONWebKey{
|
||||
Key: &priv.PublicKey,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
headers := rawHeader{
|
||||
headerEPK: makeRawMessage(b),
|
||||
}
|
||||
|
||||
return out, headers, nil
|
||||
}
|
||||
|
||||
// Decrypt the given payload and return the content encryption key.
|
||||
func (ctx ecDecrypterSigner) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
||||
epk, err := headers.getEPK()
|
||||
if err != nil {
|
||||
return nil, errors.New("go-jose/go-jose: invalid epk header")
|
||||
}
|
||||
if epk == nil {
|
||||
return nil, errors.New("go-jose/go-jose: missing epk header")
|
||||
}
|
||||
|
||||
publicKey, ok := epk.Key.(*ecdsa.PublicKey)
|
||||
if publicKey == nil || !ok {
|
||||
return nil, errors.New("go-jose/go-jose: invalid epk header")
|
||||
}
|
||||
|
||||
if !ctx.privateKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
|
||||
return nil, errors.New("go-jose/go-jose: invalid public key in epk header")
|
||||
}
|
||||
|
||||
apuData, err := headers.getAPU()
|
||||
if err != nil {
|
||||
return nil, errors.New("go-jose/go-jose: invalid apu header")
|
||||
}
|
||||
apvData, err := headers.getAPV()
|
||||
if err != nil {
|
||||
return nil, errors.New("go-jose/go-jose: invalid apv header")
|
||||
}
|
||||
|
||||
deriveKey := func(algID string, size int) []byte {
|
||||
return josecipher.DeriveECDHES(algID, apuData.bytes(), apvData.bytes(), ctx.privateKey, publicKey, size)
|
||||
}
|
||||
|
||||
var keySize int
|
||||
|
||||
algorithm := headers.getAlgorithm()
|
||||
switch algorithm {
|
||||
case ECDH_ES:
|
||||
// ECDH-ES uses direct key agreement, no key unwrapping necessary.
|
||||
return deriveKey(string(headers.getEncryption()), generator.keySize()), nil
|
||||
case ECDH_ES_A128KW:
|
||||
keySize = 16
|
||||
case ECDH_ES_A192KW:
|
||||
keySize = 24
|
||||
case ECDH_ES_A256KW:
|
||||
keySize = 32
|
||||
default:
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
key := deriveKey(string(algorithm), keySize)
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return josecipher.KeyUnwrap(block, recipient.encryptedKey)
|
||||
}
|
||||
|
||||
func (ctx edDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
||||
if alg != EdDSA {
|
||||
return Signature{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
sig, err := ctx.privateKey.Sign(RandReader, payload, crypto.Hash(0))
|
||||
if err != nil {
|
||||
return Signature{}, err
|
||||
}
|
||||
|
||||
return Signature{
|
||||
Signature: sig,
|
||||
protected: &rawHeader{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ctx edEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
|
||||
if alg != EdDSA {
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
ok := ed25519.Verify(ctx.publicKey, payload, signature)
|
||||
if !ok {
|
||||
return errors.New("go-jose/go-jose: ed25519 signature failed to verify")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sign the given payload
|
||||
func (ctx ecDecrypterSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
||||
var expectedBitSize int
|
||||
var hash crypto.Hash
|
||||
|
||||
switch alg {
|
||||
case ES256:
|
||||
expectedBitSize = 256
|
||||
hash = crypto.SHA256
|
||||
case ES384:
|
||||
expectedBitSize = 384
|
||||
hash = crypto.SHA384
|
||||
case ES512:
|
||||
expectedBitSize = 521
|
||||
hash = crypto.SHA512
|
||||
}
|
||||
|
||||
curveBits := ctx.privateKey.Curve.Params().BitSize
|
||||
if expectedBitSize != curveBits {
|
||||
return Signature{}, fmt.Errorf("go-jose/go-jose: expected %d bit key, got %d bits instead", expectedBitSize, curveBits)
|
||||
}
|
||||
|
||||
hasher := hash.New()
|
||||
|
||||
// According to documentation, Write() on hash never fails
|
||||
_, _ = hasher.Write(payload)
|
||||
hashed := hasher.Sum(nil)
|
||||
|
||||
r, s, err := ecdsa.Sign(RandReader, ctx.privateKey, hashed)
|
||||
if err != nil {
|
||||
return Signature{}, err
|
||||
}
|
||||
|
||||
keyBytes := curveBits / 8
|
||||
if curveBits%8 > 0 {
|
||||
keyBytes++
|
||||
}
|
||||
|
||||
// We serialize the outputs (r and s) into big-endian byte arrays and pad
|
||||
// them with zeros on the left to make sure the sizes work out. Both arrays
|
||||
// must be keyBytes long, and the output must be 2*keyBytes long.
|
||||
rBytes := r.Bytes()
|
||||
rBytesPadded := make([]byte, keyBytes)
|
||||
copy(rBytesPadded[keyBytes-len(rBytes):], rBytes)
|
||||
|
||||
sBytes := s.Bytes()
|
||||
sBytesPadded := make([]byte, keyBytes)
|
||||
copy(sBytesPadded[keyBytes-len(sBytes):], sBytes)
|
||||
|
||||
out := append(rBytesPadded, sBytesPadded...)
|
||||
|
||||
return Signature{
|
||||
Signature: out,
|
||||
protected: &rawHeader{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Verify the given payload
|
||||
func (ctx ecEncrypterVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
|
||||
var keySize int
|
||||
var hash crypto.Hash
|
||||
|
||||
switch alg {
|
||||
case ES256:
|
||||
keySize = 32
|
||||
hash = crypto.SHA256
|
||||
case ES384:
|
||||
keySize = 48
|
||||
hash = crypto.SHA384
|
||||
case ES512:
|
||||
keySize = 66
|
||||
hash = crypto.SHA512
|
||||
default:
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if len(signature) != 2*keySize {
|
||||
return fmt.Errorf("go-jose/go-jose: invalid signature size, have %d bytes, wanted %d", len(signature), 2*keySize)
|
||||
}
|
||||
|
||||
hasher := hash.New()
|
||||
|
||||
// According to documentation, Write() on hash never fails
|
||||
_, _ = hasher.Write(payload)
|
||||
hashed := hasher.Sum(nil)
|
||||
|
||||
r := big.NewInt(0).SetBytes(signature[:keySize])
|
||||
s := big.NewInt(0).SetBytes(signature[keySize:])
|
||||
|
||||
match := ecdsa.Verify(ctx.publicKey, hashed, r, s)
|
||||
if !match {
|
||||
return errors.New("go-jose/go-jose: ecdsa signature failed to verify")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
196
vendor/github.com/go-jose/go-jose/v3/cipher/cbc_hmac.go
generated
vendored
Normal file
196
vendor/github.com/go-jose/go-jose/v3/cipher/cbc_hmac.go
generated
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package josecipher
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"crypto/subtle"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"hash"
|
||||
)
|
||||
|
||||
const (
|
||||
nonceBytes = 16
|
||||
)
|
||||
|
||||
// NewCBCHMAC instantiates a new AEAD based on CBC+HMAC.
|
||||
func NewCBCHMAC(key []byte, newBlockCipher func([]byte) (cipher.Block, error)) (cipher.AEAD, error) {
|
||||
keySize := len(key) / 2
|
||||
integrityKey := key[:keySize]
|
||||
encryptionKey := key[keySize:]
|
||||
|
||||
blockCipher, err := newBlockCipher(encryptionKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var hash func() hash.Hash
|
||||
switch keySize {
|
||||
case 16:
|
||||
hash = sha256.New
|
||||
case 24:
|
||||
hash = sha512.New384
|
||||
case 32:
|
||||
hash = sha512.New
|
||||
}
|
||||
|
||||
return &cbcAEAD{
|
||||
hash: hash,
|
||||
blockCipher: blockCipher,
|
||||
authtagBytes: keySize,
|
||||
integrityKey: integrityKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// An AEAD based on CBC+HMAC
|
||||
type cbcAEAD struct {
|
||||
hash func() hash.Hash
|
||||
authtagBytes int
|
||||
integrityKey []byte
|
||||
blockCipher cipher.Block
|
||||
}
|
||||
|
||||
func (ctx *cbcAEAD) NonceSize() int {
|
||||
return nonceBytes
|
||||
}
|
||||
|
||||
func (ctx *cbcAEAD) Overhead() int {
|
||||
// Maximum overhead is block size (for padding) plus auth tag length, where
|
||||
// the length of the auth tag is equivalent to the key size.
|
||||
return ctx.blockCipher.BlockSize() + ctx.authtagBytes
|
||||
}
|
||||
|
||||
// Seal encrypts and authenticates the plaintext.
|
||||
func (ctx *cbcAEAD) Seal(dst, nonce, plaintext, data []byte) []byte {
|
||||
// Output buffer -- must take care not to mangle plaintext input.
|
||||
ciphertext := make([]byte, uint64(len(plaintext))+uint64(ctx.Overhead()))[:len(plaintext)]
|
||||
copy(ciphertext, plaintext)
|
||||
ciphertext = padBuffer(ciphertext, ctx.blockCipher.BlockSize())
|
||||
|
||||
cbc := cipher.NewCBCEncrypter(ctx.blockCipher, nonce)
|
||||
|
||||
cbc.CryptBlocks(ciphertext, ciphertext)
|
||||
authtag := ctx.computeAuthTag(data, nonce, ciphertext)
|
||||
|
||||
ret, out := resize(dst, uint64(len(dst))+uint64(len(ciphertext))+uint64(len(authtag)))
|
||||
copy(out, ciphertext)
|
||||
copy(out[len(ciphertext):], authtag)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Open decrypts and authenticates the ciphertext.
|
||||
func (ctx *cbcAEAD) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
|
||||
if len(ciphertext) < ctx.authtagBytes {
|
||||
return nil, errors.New("go-jose/go-jose: invalid ciphertext (too short)")
|
||||
}
|
||||
|
||||
offset := len(ciphertext) - ctx.authtagBytes
|
||||
expectedTag := ctx.computeAuthTag(data, nonce, ciphertext[:offset])
|
||||
match := subtle.ConstantTimeCompare(expectedTag, ciphertext[offset:])
|
||||
if match != 1 {
|
||||
return nil, errors.New("go-jose/go-jose: invalid ciphertext (auth tag mismatch)")
|
||||
}
|
||||
|
||||
cbc := cipher.NewCBCDecrypter(ctx.blockCipher, nonce)
|
||||
|
||||
// Make copy of ciphertext buffer, don't want to modify in place
|
||||
buffer := append([]byte{}, ciphertext[:offset]...)
|
||||
|
||||
if len(buffer)%ctx.blockCipher.BlockSize() > 0 {
|
||||
return nil, errors.New("go-jose/go-jose: invalid ciphertext (invalid length)")
|
||||
}
|
||||
|
||||
cbc.CryptBlocks(buffer, buffer)
|
||||
|
||||
// Remove padding
|
||||
plaintext, err := unpadBuffer(buffer, ctx.blockCipher.BlockSize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret, out := resize(dst, uint64(len(dst))+uint64(len(plaintext)))
|
||||
copy(out, plaintext)
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Compute an authentication tag
|
||||
func (ctx *cbcAEAD) computeAuthTag(aad, nonce, ciphertext []byte) []byte {
|
||||
buffer := make([]byte, uint64(len(aad))+uint64(len(nonce))+uint64(len(ciphertext))+8)
|
||||
n := 0
|
||||
n += copy(buffer, aad)
|
||||
n += copy(buffer[n:], nonce)
|
||||
n += copy(buffer[n:], ciphertext)
|
||||
binary.BigEndian.PutUint64(buffer[n:], uint64(len(aad))*8)
|
||||
|
||||
// According to documentation, Write() on hash.Hash never fails.
|
||||
hmac := hmac.New(ctx.hash, ctx.integrityKey)
|
||||
_, _ = hmac.Write(buffer)
|
||||
|
||||
return hmac.Sum(nil)[:ctx.authtagBytes]
|
||||
}
|
||||
|
||||
// resize ensures that the given slice has a capacity of at least n bytes.
|
||||
// If the capacity of the slice is less than n, a new slice is allocated
|
||||
// and the existing data will be copied.
|
||||
func resize(in []byte, n uint64) (head, tail []byte) {
|
||||
if uint64(cap(in)) >= n {
|
||||
head = in[:n]
|
||||
} else {
|
||||
head = make([]byte, n)
|
||||
copy(head, in)
|
||||
}
|
||||
|
||||
tail = head[len(in):]
|
||||
return
|
||||
}
|
||||
|
||||
// Apply padding
|
||||
func padBuffer(buffer []byte, blockSize int) []byte {
|
||||
missing := blockSize - (len(buffer) % blockSize)
|
||||
ret, out := resize(buffer, uint64(len(buffer))+uint64(missing))
|
||||
padding := bytes.Repeat([]byte{byte(missing)}, missing)
|
||||
copy(out, padding)
|
||||
return ret
|
||||
}
|
||||
|
||||
// Remove padding
|
||||
func unpadBuffer(buffer []byte, blockSize int) ([]byte, error) {
|
||||
if len(buffer)%blockSize != 0 {
|
||||
return nil, errors.New("go-jose/go-jose: invalid padding")
|
||||
}
|
||||
|
||||
last := buffer[len(buffer)-1]
|
||||
count := int(last)
|
||||
|
||||
if count == 0 || count > blockSize || count > len(buffer) {
|
||||
return nil, errors.New("go-jose/go-jose: invalid padding")
|
||||
}
|
||||
|
||||
padding := bytes.Repeat([]byte{last}, count)
|
||||
if !bytes.HasSuffix(buffer, padding) {
|
||||
return nil, errors.New("go-jose/go-jose: invalid padding")
|
||||
}
|
||||
|
||||
return buffer[:len(buffer)-count], nil
|
||||
}
|
75
vendor/github.com/go-jose/go-jose/v3/cipher/concat_kdf.go
generated
vendored
Normal file
75
vendor/github.com/go-jose/go-jose/v3/cipher/concat_kdf.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package josecipher
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
"io"
|
||||
)
|
||||
|
||||
type concatKDF struct {
|
||||
z, info []byte
|
||||
i uint32
|
||||
cache []byte
|
||||
hasher hash.Hash
|
||||
}
|
||||
|
||||
// NewConcatKDF builds a KDF reader based on the given inputs.
|
||||
func NewConcatKDF(hash crypto.Hash, z, algID, ptyUInfo, ptyVInfo, supPubInfo, supPrivInfo []byte) io.Reader {
|
||||
buffer := make([]byte, uint64(len(algID))+uint64(len(ptyUInfo))+uint64(len(ptyVInfo))+uint64(len(supPubInfo))+uint64(len(supPrivInfo)))
|
||||
n := 0
|
||||
n += copy(buffer, algID)
|
||||
n += copy(buffer[n:], ptyUInfo)
|
||||
n += copy(buffer[n:], ptyVInfo)
|
||||
n += copy(buffer[n:], supPubInfo)
|
||||
copy(buffer[n:], supPrivInfo)
|
||||
|
||||
hasher := hash.New()
|
||||
|
||||
return &concatKDF{
|
||||
z: z,
|
||||
info: buffer,
|
||||
hasher: hasher,
|
||||
cache: []byte{},
|
||||
i: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *concatKDF) Read(out []byte) (int, error) {
|
||||
copied := copy(out, ctx.cache)
|
||||
ctx.cache = ctx.cache[copied:]
|
||||
|
||||
for copied < len(out) {
|
||||
ctx.hasher.Reset()
|
||||
|
||||
// Write on a hash.Hash never fails
|
||||
_ = binary.Write(ctx.hasher, binary.BigEndian, ctx.i)
|
||||
_, _ = ctx.hasher.Write(ctx.z)
|
||||
_, _ = ctx.hasher.Write(ctx.info)
|
||||
|
||||
hash := ctx.hasher.Sum(nil)
|
||||
chunkCopied := copy(out[copied:], hash)
|
||||
copied += chunkCopied
|
||||
ctx.cache = hash[chunkCopied:]
|
||||
|
||||
ctx.i++
|
||||
}
|
||||
|
||||
return copied, nil
|
||||
}
|
86
vendor/github.com/go-jose/go-jose/v3/cipher/ecdh_es.go
generated
vendored
Normal file
86
vendor/github.com/go-jose/go-jose/v3/cipher/ecdh_es.go
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package josecipher
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// DeriveECDHES derives a shared encryption key using ECDH/ConcatKDF as described in JWE/JWA.
|
||||
// It is an error to call this function with a private/public key that are not on the same
|
||||
// curve. Callers must ensure that the keys are valid before calling this function. Output
|
||||
// size may be at most 1<<16 bytes (64 KiB).
|
||||
func DeriveECDHES(alg string, apuData, apvData []byte, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, size int) []byte {
|
||||
if size > 1<<16 {
|
||||
panic("ECDH-ES output size too large, must be less than or equal to 1<<16")
|
||||
}
|
||||
|
||||
// algId, partyUInfo, partyVInfo inputs must be prefixed with the length
|
||||
algID := lengthPrefixed([]byte(alg))
|
||||
ptyUInfo := lengthPrefixed(apuData)
|
||||
ptyVInfo := lengthPrefixed(apvData)
|
||||
|
||||
// suppPubInfo is the encoded length of the output size in bits
|
||||
supPubInfo := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(supPubInfo, uint32(size)*8)
|
||||
|
||||
if !priv.PublicKey.Curve.IsOnCurve(pub.X, pub.Y) {
|
||||
panic("public key not on same curve as private key")
|
||||
}
|
||||
|
||||
z, _ := priv.Curve.ScalarMult(pub.X, pub.Y, priv.D.Bytes())
|
||||
zBytes := z.Bytes()
|
||||
|
||||
// Note that calling z.Bytes() on a big.Int may strip leading zero bytes from
|
||||
// the returned byte array. This can lead to a problem where zBytes will be
|
||||
// shorter than expected which breaks the key derivation. Therefore we must pad
|
||||
// to the full length of the expected coordinate here before calling the KDF.
|
||||
octSize := dSize(priv.Curve)
|
||||
if len(zBytes) != octSize {
|
||||
zBytes = append(bytes.Repeat([]byte{0}, octSize-len(zBytes)), zBytes...)
|
||||
}
|
||||
|
||||
reader := NewConcatKDF(crypto.SHA256, zBytes, algID, ptyUInfo, ptyVInfo, supPubInfo, []byte{})
|
||||
key := make([]byte, size)
|
||||
|
||||
// Read on the KDF will never fail
|
||||
_, _ = reader.Read(key)
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
// dSize returns the size in octets for a coordinate on a elliptic curve.
|
||||
func dSize(curve elliptic.Curve) int {
|
||||
order := curve.Params().P
|
||||
bitLen := order.BitLen()
|
||||
size := bitLen / 8
|
||||
if bitLen%8 != 0 {
|
||||
size++
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func lengthPrefixed(data []byte) []byte {
|
||||
out := make([]byte, len(data)+4)
|
||||
binary.BigEndian.PutUint32(out, uint32(len(data)))
|
||||
copy(out[4:], data)
|
||||
return out
|
||||
}
|
109
vendor/github.com/go-jose/go-jose/v3/cipher/key_wrap.go
generated
vendored
Normal file
109
vendor/github.com/go-jose/go-jose/v3/cipher/key_wrap.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package josecipher
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/subtle"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var defaultIV = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}
|
||||
|
||||
// KeyWrap implements NIST key wrapping; it wraps a content encryption key (cek) with the given block cipher.
|
||||
func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) {
|
||||
if len(cek)%8 != 0 {
|
||||
return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks")
|
||||
}
|
||||
|
||||
n := len(cek) / 8
|
||||
r := make([][]byte, n)
|
||||
|
||||
for i := range r {
|
||||
r[i] = make([]byte, 8)
|
||||
copy(r[i], cek[i*8:])
|
||||
}
|
||||
|
||||
buffer := make([]byte, 16)
|
||||
tBytes := make([]byte, 8)
|
||||
copy(buffer, defaultIV)
|
||||
|
||||
for t := 0; t < 6*n; t++ {
|
||||
copy(buffer[8:], r[t%n])
|
||||
|
||||
block.Encrypt(buffer, buffer)
|
||||
|
||||
binary.BigEndian.PutUint64(tBytes, uint64(t+1))
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
buffer[i] ^= tBytes[i]
|
||||
}
|
||||
copy(r[t%n], buffer[8:])
|
||||
}
|
||||
|
||||
out := make([]byte, (n+1)*8)
|
||||
copy(out, buffer[:8])
|
||||
for i := range r {
|
||||
copy(out[(i+1)*8:], r[i])
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// KeyUnwrap implements NIST key unwrapping; it unwraps a content encryption key (cek) with the given block cipher.
|
||||
func KeyUnwrap(block cipher.Block, ciphertext []byte) ([]byte, error) {
|
||||
if len(ciphertext)%8 != 0 {
|
||||
return nil, errors.New("go-jose/go-jose: key wrap input must be 8 byte blocks")
|
||||
}
|
||||
|
||||
n := (len(ciphertext) / 8) - 1
|
||||
r := make([][]byte, n)
|
||||
|
||||
for i := range r {
|
||||
r[i] = make([]byte, 8)
|
||||
copy(r[i], ciphertext[(i+1)*8:])
|
||||
}
|
||||
|
||||
buffer := make([]byte, 16)
|
||||
tBytes := make([]byte, 8)
|
||||
copy(buffer[:8], ciphertext[:8])
|
||||
|
||||
for t := 6*n - 1; t >= 0; t-- {
|
||||
binary.BigEndian.PutUint64(tBytes, uint64(t+1))
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
buffer[i] ^= tBytes[i]
|
||||
}
|
||||
copy(buffer[8:], r[t%n])
|
||||
|
||||
block.Decrypt(buffer, buffer)
|
||||
|
||||
copy(r[t%n], buffer[8:])
|
||||
}
|
||||
|
||||
if subtle.ConstantTimeCompare(buffer[:8], defaultIV) == 0 {
|
||||
return nil, errors.New("go-jose/go-jose: failed to unwrap key")
|
||||
}
|
||||
|
||||
out := make([]byte, n*8)
|
||||
for i := range r {
|
||||
copy(out[i*8:], r[i])
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
593
vendor/github.com/go-jose/go-jose/v3/crypter.go
generated
vendored
Normal file
593
vendor/github.com/go-jose/go-jose/v3/crypter.go
generated
vendored
Normal file
@ -0,0 +1,593 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-jose/go-jose/v3/json"
|
||||
)
|
||||
|
||||
// Encrypter represents an encrypter which produces an encrypted JWE object.
|
||||
type Encrypter interface {
|
||||
Encrypt(plaintext []byte) (*JSONWebEncryption, error)
|
||||
EncryptWithAuthData(plaintext []byte, aad []byte) (*JSONWebEncryption, error)
|
||||
Options() EncrypterOptions
|
||||
}
|
||||
|
||||
// A generic content cipher
|
||||
type contentCipher interface {
|
||||
keySize() int
|
||||
encrypt(cek []byte, aad, plaintext []byte) (*aeadParts, error)
|
||||
decrypt(cek []byte, aad []byte, parts *aeadParts) ([]byte, error)
|
||||
}
|
||||
|
||||
// A key generator (for generating/getting a CEK)
|
||||
type keyGenerator interface {
|
||||
keySize() int
|
||||
genKey() ([]byte, rawHeader, error)
|
||||
}
|
||||
|
||||
// A generic key encrypter
|
||||
type keyEncrypter interface {
|
||||
encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) // Encrypt a key
|
||||
}
|
||||
|
||||
// A generic key decrypter
|
||||
type keyDecrypter interface {
|
||||
decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) // Decrypt a key
|
||||
}
|
||||
|
||||
// A generic encrypter based on the given key encrypter and content cipher.
|
||||
type genericEncrypter struct {
|
||||
contentAlg ContentEncryption
|
||||
compressionAlg CompressionAlgorithm
|
||||
cipher contentCipher
|
||||
recipients []recipientKeyInfo
|
||||
keyGenerator keyGenerator
|
||||
extraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
type recipientKeyInfo struct {
|
||||
keyID string
|
||||
keyAlg KeyAlgorithm
|
||||
keyEncrypter keyEncrypter
|
||||
}
|
||||
|
||||
// EncrypterOptions represents options that can be set on new encrypters.
|
||||
type EncrypterOptions struct {
|
||||
Compression CompressionAlgorithm
|
||||
|
||||
// Optional map of name/value pairs to be inserted into the protected
|
||||
// header of a JWS object. Some specifications which make use of
|
||||
// JWS require additional values here.
|
||||
//
|
||||
// Values will be serialized by [json.Marshal] and must be valid inputs to
|
||||
// that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
ExtraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
||||
// if necessary, and returns the updated EncrypterOptions.
|
||||
//
|
||||
// The v parameter will be serialized by [json.Marshal] and must be a valid
|
||||
// input to that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
func (eo *EncrypterOptions) WithHeader(k HeaderKey, v interface{}) *EncrypterOptions {
|
||||
if eo.ExtraHeaders == nil {
|
||||
eo.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||
}
|
||||
eo.ExtraHeaders[k] = v
|
||||
return eo
|
||||
}
|
||||
|
||||
// WithContentType adds a content type ("cty") header and returns the updated
|
||||
// EncrypterOptions.
|
||||
func (eo *EncrypterOptions) WithContentType(contentType ContentType) *EncrypterOptions {
|
||||
return eo.WithHeader(HeaderContentType, contentType)
|
||||
}
|
||||
|
||||
// WithType adds a type ("typ") header and returns the updated EncrypterOptions.
|
||||
func (eo *EncrypterOptions) WithType(typ ContentType) *EncrypterOptions {
|
||||
return eo.WithHeader(HeaderType, typ)
|
||||
}
|
||||
|
||||
// Recipient represents an algorithm/key to encrypt messages to.
|
||||
//
|
||||
// PBES2Count and PBES2Salt correspond with the "p2c" and "p2s" headers used
|
||||
// on the password-based encryption algorithms PBES2-HS256+A128KW,
|
||||
// PBES2-HS384+A192KW, and PBES2-HS512+A256KW. If they are not provided a safe
|
||||
// default of 100000 will be used for the count and a 128-bit random salt will
|
||||
// be generated.
|
||||
type Recipient struct {
|
||||
Algorithm KeyAlgorithm
|
||||
// Key must have one of these types:
|
||||
// - ed25519.PublicKey
|
||||
// - *ecdsa.PublicKey
|
||||
// - *rsa.PublicKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - []byte (a symmetric key)
|
||||
// - Any type that satisfies the OpaqueKeyEncrypter interface
|
||||
//
|
||||
// The type of Key must match the value of Algorithm.
|
||||
Key interface{}
|
||||
KeyID string
|
||||
PBES2Count int
|
||||
PBES2Salt []byte
|
||||
}
|
||||
|
||||
// NewEncrypter creates an appropriate encrypter based on the key type
|
||||
func NewEncrypter(enc ContentEncryption, rcpt Recipient, opts *EncrypterOptions) (Encrypter, error) {
|
||||
encrypter := &genericEncrypter{
|
||||
contentAlg: enc,
|
||||
recipients: []recipientKeyInfo{},
|
||||
cipher: getContentCipher(enc),
|
||||
}
|
||||
if opts != nil {
|
||||
encrypter.compressionAlg = opts.Compression
|
||||
encrypter.extraHeaders = opts.ExtraHeaders
|
||||
}
|
||||
|
||||
if encrypter.cipher == nil {
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
var keyID string
|
||||
var rawKey interface{}
|
||||
switch encryptionKey := rcpt.Key.(type) {
|
||||
case JSONWebKey:
|
||||
keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key
|
||||
case *JSONWebKey:
|
||||
keyID, rawKey = encryptionKey.KeyID, encryptionKey.Key
|
||||
case OpaqueKeyEncrypter:
|
||||
keyID, rawKey = encryptionKey.KeyID(), encryptionKey
|
||||
default:
|
||||
rawKey = encryptionKey
|
||||
}
|
||||
|
||||
switch rcpt.Algorithm {
|
||||
case DIRECT:
|
||||
// Direct encryption mode must be treated differently
|
||||
keyBytes, ok := rawKey.([]byte)
|
||||
if !ok {
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
if encrypter.cipher.keySize() != len(keyBytes) {
|
||||
return nil, ErrInvalidKeySize
|
||||
}
|
||||
encrypter.keyGenerator = staticKeyGenerator{
|
||||
key: keyBytes,
|
||||
}
|
||||
recipientInfo, _ := newSymmetricRecipient(rcpt.Algorithm, keyBytes)
|
||||
recipientInfo.keyID = keyID
|
||||
if rcpt.KeyID != "" {
|
||||
recipientInfo.keyID = rcpt.KeyID
|
||||
}
|
||||
encrypter.recipients = []recipientKeyInfo{recipientInfo}
|
||||
return encrypter, nil
|
||||
case ECDH_ES:
|
||||
// ECDH-ES (w/o key wrapping) is similar to DIRECT mode
|
||||
keyDSA, ok := rawKey.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
encrypter.keyGenerator = ecKeyGenerator{
|
||||
size: encrypter.cipher.keySize(),
|
||||
algID: string(enc),
|
||||
publicKey: keyDSA,
|
||||
}
|
||||
recipientInfo, _ := newECDHRecipient(rcpt.Algorithm, keyDSA)
|
||||
recipientInfo.keyID = keyID
|
||||
if rcpt.KeyID != "" {
|
||||
recipientInfo.keyID = rcpt.KeyID
|
||||
}
|
||||
encrypter.recipients = []recipientKeyInfo{recipientInfo}
|
||||
return encrypter, nil
|
||||
default:
|
||||
// Can just add a standard recipient
|
||||
encrypter.keyGenerator = randomKeyGenerator{
|
||||
size: encrypter.cipher.keySize(),
|
||||
}
|
||||
err := encrypter.addRecipient(rcpt)
|
||||
return encrypter, err
|
||||
}
|
||||
}
|
||||
|
||||
// NewMultiEncrypter creates a multi-encrypter based on the given parameters
|
||||
func NewMultiEncrypter(enc ContentEncryption, rcpts []Recipient, opts *EncrypterOptions) (Encrypter, error) {
|
||||
cipher := getContentCipher(enc)
|
||||
|
||||
if cipher == nil {
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
}
|
||||
if len(rcpts) == 0 {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: recipients is nil or empty")
|
||||
}
|
||||
|
||||
encrypter := &genericEncrypter{
|
||||
contentAlg: enc,
|
||||
recipients: []recipientKeyInfo{},
|
||||
cipher: cipher,
|
||||
keyGenerator: randomKeyGenerator{
|
||||
size: cipher.keySize(),
|
||||
},
|
||||
}
|
||||
|
||||
if opts != nil {
|
||||
encrypter.compressionAlg = opts.Compression
|
||||
encrypter.extraHeaders = opts.ExtraHeaders
|
||||
}
|
||||
|
||||
for _, recipient := range rcpts {
|
||||
err := encrypter.addRecipient(recipient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return encrypter, nil
|
||||
}
|
||||
|
||||
func (ctx *genericEncrypter) addRecipient(recipient Recipient) (err error) {
|
||||
var recipientInfo recipientKeyInfo
|
||||
|
||||
switch recipient.Algorithm {
|
||||
case DIRECT, ECDH_ES:
|
||||
return fmt.Errorf("go-jose/go-jose: key algorithm '%s' not supported in multi-recipient mode", recipient.Algorithm)
|
||||
}
|
||||
|
||||
recipientInfo, err = makeJWERecipient(recipient.Algorithm, recipient.Key)
|
||||
if recipient.KeyID != "" {
|
||||
recipientInfo.keyID = recipient.KeyID
|
||||
}
|
||||
|
||||
switch recipient.Algorithm {
|
||||
case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
|
||||
if sr, ok := recipientInfo.keyEncrypter.(*symmetricKeyCipher); ok {
|
||||
sr.p2c = recipient.PBES2Count
|
||||
sr.p2s = recipient.PBES2Salt
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
ctx.recipients = append(ctx.recipients, recipientInfo)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func makeJWERecipient(alg KeyAlgorithm, encryptionKey interface{}) (recipientKeyInfo, error) {
|
||||
switch encryptionKey := encryptionKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
return newRSARecipient(alg, encryptionKey)
|
||||
case *ecdsa.PublicKey:
|
||||
return newECDHRecipient(alg, encryptionKey)
|
||||
case []byte:
|
||||
return newSymmetricRecipient(alg, encryptionKey)
|
||||
case string:
|
||||
return newSymmetricRecipient(alg, []byte(encryptionKey))
|
||||
case *JSONWebKey:
|
||||
recipient, err := makeJWERecipient(alg, encryptionKey.Key)
|
||||
recipient.keyID = encryptionKey.KeyID
|
||||
return recipient, err
|
||||
case OpaqueKeyEncrypter:
|
||||
return newOpaqueKeyEncrypter(alg, encryptionKey)
|
||||
}
|
||||
return recipientKeyInfo{}, ErrUnsupportedKeyType
|
||||
}
|
||||
|
||||
// newDecrypter creates an appropriate decrypter based on the key type
|
||||
func newDecrypter(decryptionKey interface{}) (keyDecrypter, error) {
|
||||
switch decryptionKey := decryptionKey.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return &rsaDecrypterSigner{
|
||||
privateKey: decryptionKey,
|
||||
}, nil
|
||||
case *ecdsa.PrivateKey:
|
||||
return &ecDecrypterSigner{
|
||||
privateKey: decryptionKey,
|
||||
}, nil
|
||||
case []byte:
|
||||
return &symmetricKeyCipher{
|
||||
key: decryptionKey,
|
||||
}, nil
|
||||
case string:
|
||||
return &symmetricKeyCipher{
|
||||
key: []byte(decryptionKey),
|
||||
}, nil
|
||||
case JSONWebKey:
|
||||
return newDecrypter(decryptionKey.Key)
|
||||
case *JSONWebKey:
|
||||
return newDecrypter(decryptionKey.Key)
|
||||
case OpaqueKeyDecrypter:
|
||||
return &opaqueKeyDecrypter{decrypter: decryptionKey}, nil
|
||||
default:
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of encrypt method producing a JWE object.
|
||||
func (ctx *genericEncrypter) Encrypt(plaintext []byte) (*JSONWebEncryption, error) {
|
||||
return ctx.EncryptWithAuthData(plaintext, nil)
|
||||
}
|
||||
|
||||
// Implementation of encrypt method producing a JWE object.
|
||||
func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWebEncryption, error) {
|
||||
obj := &JSONWebEncryption{}
|
||||
obj.aad = aad
|
||||
|
||||
obj.protected = &rawHeader{}
|
||||
err := obj.protected.set(headerEncryption, ctx.contentAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj.recipients = make([]recipientInfo, len(ctx.recipients))
|
||||
|
||||
if len(ctx.recipients) == 0 {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: no recipients to encrypt to")
|
||||
}
|
||||
|
||||
cek, headers, err := ctx.keyGenerator.genKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj.protected.merge(&headers)
|
||||
|
||||
for i, info := range ctx.recipients {
|
||||
recipient, err := info.keyEncrypter.encryptKey(cek, info.keyAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = recipient.header.set(headerAlgorithm, info.keyAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if info.keyID != "" {
|
||||
err = recipient.header.set(headerKeyID, info.keyID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
obj.recipients[i] = recipient
|
||||
}
|
||||
|
||||
if len(ctx.recipients) == 1 {
|
||||
// Move per-recipient headers into main protected header if there's
|
||||
// only a single recipient.
|
||||
obj.protected.merge(obj.recipients[0].header)
|
||||
obj.recipients[0].header = nil
|
||||
}
|
||||
|
||||
if ctx.compressionAlg != NONE {
|
||||
plaintext, err = compress(ctx.compressionAlg, plaintext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = obj.protected.set(headerCompression, ctx.compressionAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range ctx.extraHeaders {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
(*obj.protected)[k] = makeRawMessage(b)
|
||||
}
|
||||
|
||||
authData := obj.computeAuthData()
|
||||
parts, err := ctx.cipher.encrypt(cek, authData, plaintext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj.iv = parts.iv
|
||||
obj.ciphertext = parts.ciphertext
|
||||
obj.tag = parts.tag
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (ctx *genericEncrypter) Options() EncrypterOptions {
|
||||
return EncrypterOptions{
|
||||
Compression: ctx.compressionAlg,
|
||||
ExtraHeaders: ctx.extraHeaders,
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypt and validate the object and return the plaintext. This
|
||||
// function does not support multi-recipient. If you desire multi-recipient
|
||||
// decryption use DecryptMulti instead.
|
||||
//
|
||||
// The decryptionKey argument must contain a private or symmetric key
|
||||
// and must have one of these types:
|
||||
// - *ecdsa.PrivateKey
|
||||
// - *rsa.PrivateKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - *JSONWebKeySet
|
||||
// - JSONWebKeySet
|
||||
// - []byte (a symmetric key)
|
||||
// - string (a symmetric key)
|
||||
// - Any type that satisfies the OpaqueKeyDecrypter interface.
|
||||
//
|
||||
// Note that ed25519 is only available for signatures, not encryption, so is
|
||||
// not an option here.
|
||||
//
|
||||
// Automatically decompresses plaintext, but returns an error if the decompressed
|
||||
// data would be >250kB or >10x the size of the compressed data, whichever is larger.
|
||||
func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error) {
|
||||
headers := obj.mergedHeaders(nil)
|
||||
|
||||
if len(obj.recipients) > 1 {
|
||||
return nil, errors.New("go-jose/go-jose: too many recipients in payload; expecting only one")
|
||||
}
|
||||
|
||||
critical, err := headers.getCritical()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid crit header")
|
||||
}
|
||||
|
||||
if len(critical) > 0 {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
|
||||
}
|
||||
|
||||
key := tryJWKS(decryptionKey, obj.Header)
|
||||
decrypter, err := newDecrypter(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cipher := getContentCipher(headers.getEncryption())
|
||||
if cipher == nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(headers.getEncryption()))
|
||||
}
|
||||
|
||||
generator := randomKeyGenerator{
|
||||
size: cipher.keySize(),
|
||||
}
|
||||
|
||||
parts := &aeadParts{
|
||||
iv: obj.iv,
|
||||
ciphertext: obj.ciphertext,
|
||||
tag: obj.tag,
|
||||
}
|
||||
|
||||
authData := obj.computeAuthData()
|
||||
|
||||
var plaintext []byte
|
||||
recipient := obj.recipients[0]
|
||||
recipientHeaders := obj.mergedHeaders(&recipient)
|
||||
|
||||
cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator)
|
||||
if err == nil {
|
||||
// Found a valid CEK -- let's try to decrypt.
|
||||
plaintext, err = cipher.decrypt(cek, authData, parts)
|
||||
}
|
||||
|
||||
if plaintext == nil {
|
||||
return nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
// The "zip" header parameter may only be present in the protected header.
|
||||
if comp := obj.protected.getCompression(); comp != "" {
|
||||
plaintext, err = decompress(comp, plaintext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
// DecryptMulti decrypts and validates the object and returns the plaintexts,
|
||||
// with support for multiple recipients. It returns the index of the recipient
|
||||
// for which the decryption was successful, the merged headers for that recipient,
|
||||
// and the plaintext.
|
||||
//
|
||||
// The decryptionKey argument must have one of the types allowed for the
|
||||
// decryptionKey argument of Decrypt().
|
||||
//
|
||||
// Automatically decompresses plaintext, but returns an error if the decompressed
|
||||
// data would be >250kB or >3x the size of the compressed data, whichever is larger.
|
||||
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
|
||||
globalHeaders := obj.mergedHeaders(nil)
|
||||
|
||||
critical, err := globalHeaders.getCritical()
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: invalid crit header")
|
||||
}
|
||||
|
||||
if len(critical) > 0 {
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported crit header")
|
||||
}
|
||||
|
||||
key := tryJWKS(decryptionKey, obj.Header)
|
||||
decrypter, err := newDecrypter(key)
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, err
|
||||
}
|
||||
|
||||
encryption := globalHeaders.getEncryption()
|
||||
cipher := getContentCipher(encryption)
|
||||
if cipher == nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: unsupported enc value '%s'", string(encryption))
|
||||
}
|
||||
|
||||
generator := randomKeyGenerator{
|
||||
size: cipher.keySize(),
|
||||
}
|
||||
|
||||
parts := &aeadParts{
|
||||
iv: obj.iv,
|
||||
ciphertext: obj.ciphertext,
|
||||
tag: obj.tag,
|
||||
}
|
||||
|
||||
authData := obj.computeAuthData()
|
||||
|
||||
index := -1
|
||||
var plaintext []byte
|
||||
var headers rawHeader
|
||||
|
||||
for i, recipient := range obj.recipients {
|
||||
recipientHeaders := obj.mergedHeaders(&recipient)
|
||||
|
||||
cek, err := decrypter.decryptKey(recipientHeaders, &recipient, generator)
|
||||
if err == nil {
|
||||
// Found a valid CEK -- let's try to decrypt.
|
||||
plaintext, err = cipher.decrypt(cek, authData, parts)
|
||||
if err == nil {
|
||||
index = i
|
||||
headers = recipientHeaders
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if plaintext == nil {
|
||||
return -1, Header{}, nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
// The "zip" header parameter may only be present in the protected header.
|
||||
if comp := obj.protected.getCompression(); comp != "" {
|
||||
plaintext, err = decompress(comp, plaintext)
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to decompress plaintext: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
sanitized, err := headers.sanitized()
|
||||
if err != nil {
|
||||
return -1, Header{}, nil, fmt.Errorf("go-jose/go-jose: failed to sanitize header: %v", err)
|
||||
}
|
||||
|
||||
return index, sanitized, plaintext, err
|
||||
}
|
25
vendor/github.com/go-jose/go-jose/v3/doc.go
generated
vendored
Normal file
25
vendor/github.com/go-jose/go-jose/v3/doc.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Package jose aims to provide an implementation of the Javascript Object Signing
|
||||
and Encryption set of standards. It implements encryption and signing based on
|
||||
the JSON Web Encryption and JSON Web Signature standards, with optional JSON Web
|
||||
Token support available in a sub-package. The library supports both the compact
|
||||
and JWS/JWE JSON Serialization formats, and has optional support for multiple
|
||||
recipients.
|
||||
*/
|
||||
package jose
|
237
vendor/github.com/go-jose/go-jose/v3/encoding.go
generated
vendored
Normal file
237
vendor/github.com/go-jose/go-jose/v3/encoding.go
generated
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/flate"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/go-jose/go-jose/v3/json"
|
||||
)
|
||||
|
||||
// Helper function to serialize known-good objects.
|
||||
// Precondition: value is not a nil pointer.
|
||||
func mustSerializeJSON(value interface{}) []byte {
|
||||
out, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// We never want to serialize the top-level value "null," since it's not a
|
||||
// valid JOSE message. But if a caller passes in a nil pointer to this method,
|
||||
// MarshalJSON will happily serialize it as the top-level value "null". If
|
||||
// that value is then embedded in another operation, for instance by being
|
||||
// base64-encoded and fed as input to a signing algorithm
|
||||
// (https://github.com/go-jose/go-jose/issues/22), the result will be
|
||||
// incorrect. Because this method is intended for known-good objects, and a nil
|
||||
// pointer is not a known-good object, we are free to panic in this case.
|
||||
// Note: It's not possible to directly check whether the data pointed at by an
|
||||
// interface is a nil pointer, so we do this hacky workaround.
|
||||
// https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I
|
||||
if string(out) == "null" {
|
||||
panic("Tried to serialize a nil pointer.")
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Strip all newlines and whitespace
|
||||
func stripWhitespace(data string) string {
|
||||
buf := strings.Builder{}
|
||||
buf.Grow(len(data))
|
||||
for _, r := range data {
|
||||
if !unicode.IsSpace(r) {
|
||||
buf.WriteRune(r)
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// Perform compression based on algorithm
|
||||
func compress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) {
|
||||
switch algorithm {
|
||||
case DEFLATE:
|
||||
return deflate(input)
|
||||
default:
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
}
|
||||
}
|
||||
|
||||
// Perform decompression based on algorithm
|
||||
func decompress(algorithm CompressionAlgorithm, input []byte) ([]byte, error) {
|
||||
switch algorithm {
|
||||
case DEFLATE:
|
||||
return inflate(input)
|
||||
default:
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
}
|
||||
}
|
||||
|
||||
// deflate compresses the input.
|
||||
func deflate(input []byte) ([]byte, error) {
|
||||
output := new(bytes.Buffer)
|
||||
|
||||
// Writing to byte buffer, err is always nil
|
||||
writer, _ := flate.NewWriter(output, 1)
|
||||
_, _ = io.Copy(writer, bytes.NewBuffer(input))
|
||||
|
||||
err := writer.Close()
|
||||
return output.Bytes(), err
|
||||
}
|
||||
|
||||
// inflate decompresses the input.
|
||||
//
|
||||
// Errors if the decompressed data would be >250kB or >10x the size of the
|
||||
// compressed data, whichever is larger.
|
||||
func inflate(input []byte) ([]byte, error) {
|
||||
output := new(bytes.Buffer)
|
||||
reader := flate.NewReader(bytes.NewBuffer(input))
|
||||
|
||||
maxCompressedSize := 10 * int64(len(input))
|
||||
if maxCompressedSize < 250000 {
|
||||
maxCompressedSize = 250000
|
||||
}
|
||||
|
||||
limit := maxCompressedSize + 1
|
||||
n, err := io.CopyN(output, reader, limit)
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
if n == limit {
|
||||
return nil, fmt.Errorf("uncompressed data would be too large (>%d bytes)", maxCompressedSize)
|
||||
}
|
||||
|
||||
err = reader.Close()
|
||||
return output.Bytes(), err
|
||||
}
|
||||
|
||||
// byteBuffer represents a slice of bytes that can be serialized to url-safe base64.
|
||||
type byteBuffer struct {
|
||||
data []byte
|
||||
}
|
||||
|
||||
func newBuffer(data []byte) *byteBuffer {
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
return &byteBuffer{
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func newFixedSizeBuffer(data []byte, length int) *byteBuffer {
|
||||
if len(data) > length {
|
||||
panic("go-jose/go-jose: invalid call to newFixedSizeBuffer (len(data) > length)")
|
||||
}
|
||||
pad := make([]byte, length-len(data))
|
||||
return newBuffer(append(pad, data...))
|
||||
}
|
||||
|
||||
func newBufferFromInt(num uint64) *byteBuffer {
|
||||
data := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(data, num)
|
||||
return newBuffer(bytes.TrimLeft(data, "\x00"))
|
||||
}
|
||||
|
||||
func (b *byteBuffer) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(b.base64())
|
||||
}
|
||||
|
||||
func (b *byteBuffer) UnmarshalJSON(data []byte) error {
|
||||
var encoded string
|
||||
err := json.Unmarshal(data, &encoded)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if encoded == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
decoded, err := base64URLDecode(encoded)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*b = *newBuffer(decoded)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *byteBuffer) base64() string {
|
||||
return base64.RawURLEncoding.EncodeToString(b.data)
|
||||
}
|
||||
|
||||
func (b *byteBuffer) bytes() []byte {
|
||||
// Handling nil here allows us to transparently handle nil slices when serializing.
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
return b.data
|
||||
}
|
||||
|
||||
func (b byteBuffer) bigInt() *big.Int {
|
||||
return new(big.Int).SetBytes(b.data)
|
||||
}
|
||||
|
||||
func (b byteBuffer) toInt() int {
|
||||
return int(b.bigInt().Int64())
|
||||
}
|
||||
|
||||
// base64URLDecode is implemented as defined in https://www.rfc-editor.org/rfc/rfc7515.html#appendix-C
|
||||
func base64URLDecode(value string) ([]byte, error) {
|
||||
value = strings.TrimRight(value, "=")
|
||||
return base64.RawURLEncoding.DecodeString(value)
|
||||
}
|
||||
|
||||
func base64EncodeLen(sl []byte) int {
|
||||
return base64.RawURLEncoding.EncodedLen(len(sl))
|
||||
}
|
||||
|
||||
func base64JoinWithDots(inputs ...[]byte) string {
|
||||
if len(inputs) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Count of dots.
|
||||
totalCount := len(inputs) - 1
|
||||
|
||||
for _, input := range inputs {
|
||||
totalCount += base64EncodeLen(input)
|
||||
}
|
||||
|
||||
out := make([]byte, totalCount)
|
||||
startEncode := 0
|
||||
for i, input := range inputs {
|
||||
base64.RawURLEncoding.Encode(out[startEncode:], input)
|
||||
|
||||
if i == len(inputs)-1 {
|
||||
continue
|
||||
}
|
||||
|
||||
startEncode += base64EncodeLen(input)
|
||||
out[startEncode] = '.'
|
||||
startEncode++
|
||||
}
|
||||
|
||||
return string(out)
|
||||
}
|
27
vendor/github.com/go-jose/go-jose/v3/json/LICENSE
generated
vendored
Normal file
27
vendor/github.com/go-jose/go-jose/v3/json/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
13
vendor/github.com/go-jose/go-jose/v3/json/README.md
generated
vendored
Normal file
13
vendor/github.com/go-jose/go-jose/v3/json/README.md
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Safe JSON
|
||||
|
||||
This repository contains a fork of the `encoding/json` package from Go 1.6.
|
||||
|
||||
The following changes were made:
|
||||
|
||||
* Object deserialization uses case-sensitive member name matching instead of
|
||||
[case-insensitive matching](https://www.ietf.org/mail-archive/web/json/current/msg03763.html).
|
||||
This is to avoid differences in the interpretation of JOSE messages between
|
||||
go-jose and libraries written in other languages.
|
||||
* When deserializing a JSON object, we check for duplicate keys and reject the
|
||||
input whenever we detect a duplicate. Rather than trying to work with malformed
|
||||
data, we prefer to reject it right away.
|
1216
vendor/github.com/go-jose/go-jose/v3/json/decode.go
generated
vendored
Normal file
1216
vendor/github.com/go-jose/go-jose/v3/json/decode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1197
vendor/github.com/go-jose/go-jose/v3/json/encode.go
generated
vendored
Normal file
1197
vendor/github.com/go-jose/go-jose/v3/json/encode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
141
vendor/github.com/go-jose/go-jose/v3/json/indent.go
generated
vendored
Normal file
141
vendor/github.com/go-jose/go-jose/v3/json/indent.go
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import "bytes"
|
||||
|
||||
// Compact appends to dst the JSON-encoded src with
|
||||
// insignificant space characters elided.
|
||||
func Compact(dst *bytes.Buffer, src []byte) error {
|
||||
return compact(dst, src, false)
|
||||
}
|
||||
|
||||
func compact(dst *bytes.Buffer, src []byte, escape bool) error {
|
||||
origLen := dst.Len()
|
||||
var scan scanner
|
||||
scan.reset()
|
||||
start := 0
|
||||
for i, c := range src {
|
||||
if escape && (c == '<' || c == '>' || c == '&') {
|
||||
if start < i {
|
||||
dst.Write(src[start:i])
|
||||
}
|
||||
dst.WriteString(`\u00`)
|
||||
dst.WriteByte(hex[c>>4])
|
||||
dst.WriteByte(hex[c&0xF])
|
||||
start = i + 1
|
||||
}
|
||||
// Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
|
||||
if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
|
||||
if start < i {
|
||||
dst.Write(src[start:i])
|
||||
}
|
||||
dst.WriteString(`\u202`)
|
||||
dst.WriteByte(hex[src[i+2]&0xF])
|
||||
start = i + 3
|
||||
}
|
||||
v := scan.step(&scan, c)
|
||||
if v >= scanSkipSpace {
|
||||
if v == scanError {
|
||||
break
|
||||
}
|
||||
if start < i {
|
||||
dst.Write(src[start:i])
|
||||
}
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
dst.Truncate(origLen)
|
||||
return scan.err
|
||||
}
|
||||
if start < len(src) {
|
||||
dst.Write(src[start:])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
|
||||
dst.WriteByte('\n')
|
||||
dst.WriteString(prefix)
|
||||
for i := 0; i < depth; i++ {
|
||||
dst.WriteString(indent)
|
||||
}
|
||||
}
|
||||
|
||||
// Indent appends to dst an indented form of the JSON-encoded src.
|
||||
// Each element in a JSON object or array begins on a new,
|
||||
// indented line beginning with prefix followed by one or more
|
||||
// copies of indent according to the indentation nesting.
|
||||
// The data appended to dst does not begin with the prefix nor
|
||||
// any indentation, to make it easier to embed inside other formatted JSON data.
|
||||
// Although leading space characters (space, tab, carriage return, newline)
|
||||
// at the beginning of src are dropped, trailing space characters
|
||||
// at the end of src are preserved and copied to dst.
|
||||
// For example, if src has no trailing spaces, neither will dst;
|
||||
// if src ends in a trailing newline, so will dst.
|
||||
func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
|
||||
origLen := dst.Len()
|
||||
var scan scanner
|
||||
scan.reset()
|
||||
needIndent := false
|
||||
depth := 0
|
||||
for _, c := range src {
|
||||
scan.bytes++
|
||||
v := scan.step(&scan, c)
|
||||
if v == scanSkipSpace {
|
||||
continue
|
||||
}
|
||||
if v == scanError {
|
||||
break
|
||||
}
|
||||
if needIndent && v != scanEndObject && v != scanEndArray {
|
||||
needIndent = false
|
||||
depth++
|
||||
newline(dst, prefix, indent, depth)
|
||||
}
|
||||
|
||||
// Emit semantically uninteresting bytes
|
||||
// (in particular, punctuation in strings) unmodified.
|
||||
if v == scanContinue {
|
||||
dst.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
|
||||
// Add spacing around real punctuation.
|
||||
switch c {
|
||||
case '{', '[':
|
||||
// delay indent so that empty object and array are formatted as {} and [].
|
||||
needIndent = true
|
||||
dst.WriteByte(c)
|
||||
|
||||
case ',':
|
||||
dst.WriteByte(c)
|
||||
newline(dst, prefix, indent, depth)
|
||||
|
||||
case ':':
|
||||
dst.WriteByte(c)
|
||||
dst.WriteByte(' ')
|
||||
|
||||
case '}', ']':
|
||||
if needIndent {
|
||||
// suppress indent in empty object/array
|
||||
needIndent = false
|
||||
} else {
|
||||
depth--
|
||||
newline(dst, prefix, indent, depth)
|
||||
}
|
||||
dst.WriteByte(c)
|
||||
|
||||
default:
|
||||
dst.WriteByte(c)
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
dst.Truncate(origLen)
|
||||
return scan.err
|
||||
}
|
||||
return nil
|
||||
}
|
623
vendor/github.com/go-jose/go-jose/v3/json/scanner.go
generated
vendored
Normal file
623
vendor/github.com/go-jose/go-jose/v3/json/scanner.go
generated
vendored
Normal file
@ -0,0 +1,623 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
// JSON value parser state machine.
|
||||
// Just about at the limit of what is reasonable to write by hand.
|
||||
// Some parts are a bit tedious, but overall it nicely factors out the
|
||||
// otherwise common code from the multiple scanning functions
|
||||
// in this package (Compact, Indent, checkValid, nextValue, etc).
|
||||
//
|
||||
// This file starts with two simple examples using the scanner
|
||||
// before diving into the scanner itself.
|
||||
|
||||
import "strconv"
|
||||
|
||||
// checkValid verifies that data is valid JSON-encoded data.
|
||||
// scan is passed in for use by checkValid to avoid an allocation.
|
||||
func checkValid(data []byte, scan *scanner) error {
|
||||
scan.reset()
|
||||
for _, c := range data {
|
||||
scan.bytes++
|
||||
if scan.step(scan, c) == scanError {
|
||||
return scan.err
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
return scan.err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// nextValue splits data after the next whole JSON value,
|
||||
// returning that value and the bytes that follow it as separate slices.
|
||||
// scan is passed in for use by nextValue to avoid an allocation.
|
||||
func nextValue(data []byte, scan *scanner) (value, rest []byte, err error) {
|
||||
scan.reset()
|
||||
for i, c := range data {
|
||||
v := scan.step(scan, c)
|
||||
if v >= scanEndObject {
|
||||
switch v {
|
||||
// probe the scanner with a space to determine whether we will
|
||||
// get scanEnd on the next character. Otherwise, if the next character
|
||||
// is not a space, scanEndTop allocates a needless error.
|
||||
case scanEndObject, scanEndArray:
|
||||
if scan.step(scan, ' ') == scanEnd {
|
||||
return data[:i+1], data[i+1:], nil
|
||||
}
|
||||
case scanError:
|
||||
return nil, nil, scan.err
|
||||
case scanEnd:
|
||||
return data[:i], data[i:], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if scan.eof() == scanError {
|
||||
return nil, nil, scan.err
|
||||
}
|
||||
return data, nil, nil
|
||||
}
|
||||
|
||||
// A SyntaxError is a description of a JSON syntax error.
|
||||
type SyntaxError struct {
|
||||
msg string // description of error
|
||||
Offset int64 // error occurred after reading Offset bytes
|
||||
}
|
||||
|
||||
func (e *SyntaxError) Error() string { return e.msg }
|
||||
|
||||
// A scanner is a JSON scanning state machine.
|
||||
// Callers call scan.reset() and then pass bytes in one at a time
|
||||
// by calling scan.step(&scan, c) for each byte.
|
||||
// The return value, referred to as an opcode, tells the
|
||||
// caller about significant parsing events like beginning
|
||||
// and ending literals, objects, and arrays, so that the
|
||||
// caller can follow along if it wishes.
|
||||
// The return value scanEnd indicates that a single top-level
|
||||
// JSON value has been completed, *before* the byte that
|
||||
// just got passed in. (The indication must be delayed in order
|
||||
// to recognize the end of numbers: is 123 a whole value or
|
||||
// the beginning of 12345e+6?).
|
||||
type scanner struct {
|
||||
// The step is a func to be called to execute the next transition.
|
||||
// Also tried using an integer constant and a single func
|
||||
// with a switch, but using the func directly was 10% faster
|
||||
// on a 64-bit Mac Mini, and it's nicer to read.
|
||||
step func(*scanner, byte) int
|
||||
|
||||
// Reached end of top-level value.
|
||||
endTop bool
|
||||
|
||||
// Stack of what we're in the middle of - array values, object keys, object values.
|
||||
parseState []int
|
||||
|
||||
// Error that happened, if any.
|
||||
err error
|
||||
|
||||
// 1-byte redo (see undo method)
|
||||
redo bool
|
||||
redoCode int
|
||||
redoState func(*scanner, byte) int
|
||||
|
||||
// total bytes consumed, updated by decoder.Decode
|
||||
bytes int64
|
||||
}
|
||||
|
||||
// These values are returned by the state transition functions
|
||||
// assigned to scanner.state and the method scanner.eof.
|
||||
// They give details about the current state of the scan that
|
||||
// callers might be interested to know about.
|
||||
// It is okay to ignore the return value of any particular
|
||||
// call to scanner.state: if one call returns scanError,
|
||||
// every subsequent call will return scanError too.
|
||||
const (
|
||||
// Continue.
|
||||
scanContinue = iota // uninteresting byte
|
||||
scanBeginLiteral // end implied by next result != scanContinue
|
||||
scanBeginObject // begin object
|
||||
scanObjectKey // just finished object key (string)
|
||||
scanObjectValue // just finished non-last object value
|
||||
scanEndObject // end object (implies scanObjectValue if possible)
|
||||
scanBeginArray // begin array
|
||||
scanArrayValue // just finished array value
|
||||
scanEndArray // end array (implies scanArrayValue if possible)
|
||||
scanSkipSpace // space byte; can skip; known to be last "continue" result
|
||||
|
||||
// Stop.
|
||||
scanEnd // top-level value ended *before* this byte; known to be first "stop" result
|
||||
scanError // hit an error, scanner.err.
|
||||
)
|
||||
|
||||
// These values are stored in the parseState stack.
|
||||
// They give the current state of a composite value
|
||||
// being scanned. If the parser is inside a nested value
|
||||
// the parseState describes the nested state, outermost at entry 0.
|
||||
const (
|
||||
parseObjectKey = iota // parsing object key (before colon)
|
||||
parseObjectValue // parsing object value (after colon)
|
||||
parseArrayValue // parsing array value
|
||||
)
|
||||
|
||||
// reset prepares the scanner for use.
|
||||
// It must be called before calling s.step.
|
||||
func (s *scanner) reset() {
|
||||
s.step = stateBeginValue
|
||||
s.parseState = s.parseState[0:0]
|
||||
s.err = nil
|
||||
s.redo = false
|
||||
s.endTop = false
|
||||
}
|
||||
|
||||
// eof tells the scanner that the end of input has been reached.
|
||||
// It returns a scan status just as s.step does.
|
||||
func (s *scanner) eof() int {
|
||||
if s.err != nil {
|
||||
return scanError
|
||||
}
|
||||
if s.endTop {
|
||||
return scanEnd
|
||||
}
|
||||
s.step(s, ' ')
|
||||
if s.endTop {
|
||||
return scanEnd
|
||||
}
|
||||
if s.err == nil {
|
||||
s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
|
||||
}
|
||||
return scanError
|
||||
}
|
||||
|
||||
// pushParseState pushes a new parse state p onto the parse stack.
|
||||
func (s *scanner) pushParseState(p int) {
|
||||
s.parseState = append(s.parseState, p)
|
||||
}
|
||||
|
||||
// popParseState pops a parse state (already obtained) off the stack
|
||||
// and updates s.step accordingly.
|
||||
func (s *scanner) popParseState() {
|
||||
n := len(s.parseState) - 1
|
||||
s.parseState = s.parseState[0:n]
|
||||
s.redo = false
|
||||
if n == 0 {
|
||||
s.step = stateEndTop
|
||||
s.endTop = true
|
||||
} else {
|
||||
s.step = stateEndValue
|
||||
}
|
||||
}
|
||||
|
||||
func isSpace(c byte) bool {
|
||||
return c == ' ' || c == '\t' || c == '\r' || c == '\n'
|
||||
}
|
||||
|
||||
// stateBeginValueOrEmpty is the state after reading `[`.
|
||||
func stateBeginValueOrEmpty(s *scanner, c byte) int {
|
||||
if c <= ' ' && isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
if c == ']' {
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
return stateBeginValue(s, c)
|
||||
}
|
||||
|
||||
// stateBeginValue is the state at the beginning of the input.
|
||||
func stateBeginValue(s *scanner, c byte) int {
|
||||
if c <= ' ' && isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
switch c {
|
||||
case '{':
|
||||
s.step = stateBeginStringOrEmpty
|
||||
s.pushParseState(parseObjectKey)
|
||||
return scanBeginObject
|
||||
case '[':
|
||||
s.step = stateBeginValueOrEmpty
|
||||
s.pushParseState(parseArrayValue)
|
||||
return scanBeginArray
|
||||
case '"':
|
||||
s.step = stateInString
|
||||
return scanBeginLiteral
|
||||
case '-':
|
||||
s.step = stateNeg
|
||||
return scanBeginLiteral
|
||||
case '0': // beginning of 0.123
|
||||
s.step = state0
|
||||
return scanBeginLiteral
|
||||
case 't': // beginning of true
|
||||
s.step = stateT
|
||||
return scanBeginLiteral
|
||||
case 'f': // beginning of false
|
||||
s.step = stateF
|
||||
return scanBeginLiteral
|
||||
case 'n': // beginning of null
|
||||
s.step = stateN
|
||||
return scanBeginLiteral
|
||||
}
|
||||
if '1' <= c && c <= '9' { // beginning of 1234.5
|
||||
s.step = state1
|
||||
return scanBeginLiteral
|
||||
}
|
||||
return s.error(c, "looking for beginning of value")
|
||||
}
|
||||
|
||||
// stateBeginStringOrEmpty is the state after reading `{`.
|
||||
func stateBeginStringOrEmpty(s *scanner, c byte) int {
|
||||
if c <= ' ' && isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
if c == '}' {
|
||||
n := len(s.parseState)
|
||||
s.parseState[n-1] = parseObjectValue
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
return stateBeginString(s, c)
|
||||
}
|
||||
|
||||
// stateBeginString is the state after reading `{"key": value,`.
|
||||
func stateBeginString(s *scanner, c byte) int {
|
||||
if c <= ' ' && isSpace(c) {
|
||||
return scanSkipSpace
|
||||
}
|
||||
if c == '"' {
|
||||
s.step = stateInString
|
||||
return scanBeginLiteral
|
||||
}
|
||||
return s.error(c, "looking for beginning of object key string")
|
||||
}
|
||||
|
||||
// stateEndValue is the state after completing a value,
|
||||
// such as after reading `{}` or `true` or `["x"`.
|
||||
func stateEndValue(s *scanner, c byte) int {
|
||||
n := len(s.parseState)
|
||||
if n == 0 {
|
||||
// Completed top-level before the current byte.
|
||||
s.step = stateEndTop
|
||||
s.endTop = true
|
||||
return stateEndTop(s, c)
|
||||
}
|
||||
if c <= ' ' && isSpace(c) {
|
||||
s.step = stateEndValue
|
||||
return scanSkipSpace
|
||||
}
|
||||
ps := s.parseState[n-1]
|
||||
switch ps {
|
||||
case parseObjectKey:
|
||||
if c == ':' {
|
||||
s.parseState[n-1] = parseObjectValue
|
||||
s.step = stateBeginValue
|
||||
return scanObjectKey
|
||||
}
|
||||
return s.error(c, "after object key")
|
||||
case parseObjectValue:
|
||||
if c == ',' {
|
||||
s.parseState[n-1] = parseObjectKey
|
||||
s.step = stateBeginString
|
||||
return scanObjectValue
|
||||
}
|
||||
if c == '}' {
|
||||
s.popParseState()
|
||||
return scanEndObject
|
||||
}
|
||||
return s.error(c, "after object key:value pair")
|
||||
case parseArrayValue:
|
||||
if c == ',' {
|
||||
s.step = stateBeginValue
|
||||
return scanArrayValue
|
||||
}
|
||||
if c == ']' {
|
||||
s.popParseState()
|
||||
return scanEndArray
|
||||
}
|
||||
return s.error(c, "after array element")
|
||||
}
|
||||
return s.error(c, "")
|
||||
}
|
||||
|
||||
// stateEndTop is the state after finishing the top-level value,
|
||||
// such as after reading `{}` or `[1,2,3]`.
|
||||
// Only space characters should be seen now.
|
||||
func stateEndTop(s *scanner, c byte) int {
|
||||
if c != ' ' && c != '\t' && c != '\r' && c != '\n' {
|
||||
// Complain about non-space byte on next call.
|
||||
s.error(c, "after top-level value")
|
||||
}
|
||||
return scanEnd
|
||||
}
|
||||
|
||||
// stateInString is the state after reading `"`.
|
||||
func stateInString(s *scanner, c byte) int {
|
||||
if c == '"' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
if c == '\\' {
|
||||
s.step = stateInStringEsc
|
||||
return scanContinue
|
||||
}
|
||||
if c < 0x20 {
|
||||
return s.error(c, "in string literal")
|
||||
}
|
||||
return scanContinue
|
||||
}
|
||||
|
||||
// stateInStringEsc is the state after reading `"\` during a quoted string.
|
||||
func stateInStringEsc(s *scanner, c byte) int {
|
||||
switch c {
|
||||
case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
|
||||
s.step = stateInString
|
||||
return scanContinue
|
||||
case 'u':
|
||||
s.step = stateInStringEscU
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in string escape code")
|
||||
}
|
||||
|
||||
// stateInStringEscU is the state after reading `"\u` during a quoted string.
|
||||
func stateInStringEscU(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInStringEscU1
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateInStringEscU1 is the state after reading `"\u1` during a quoted string.
|
||||
func stateInStringEscU1(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInStringEscU12
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateInStringEscU12 is the state after reading `"\u12` during a quoted string.
|
||||
func stateInStringEscU12(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInStringEscU123
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateInStringEscU123 is the state after reading `"\u123` during a quoted string.
|
||||
func stateInStringEscU123(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
|
||||
s.step = stateInString
|
||||
return scanContinue
|
||||
}
|
||||
// numbers
|
||||
return s.error(c, "in \\u hexadecimal character escape")
|
||||
}
|
||||
|
||||
// stateNeg is the state after reading `-` during a number.
|
||||
func stateNeg(s *scanner, c byte) int {
|
||||
if c == '0' {
|
||||
s.step = state0
|
||||
return scanContinue
|
||||
}
|
||||
if '1' <= c && c <= '9' {
|
||||
s.step = state1
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in numeric literal")
|
||||
}
|
||||
|
||||
// state1 is the state after reading a non-zero integer during a number,
|
||||
// such as after reading `1` or `100` but not `0`.
|
||||
func state1(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
s.step = state1
|
||||
return scanContinue
|
||||
}
|
||||
return state0(s, c)
|
||||
}
|
||||
|
||||
// state0 is the state after reading `0` during a number.
|
||||
func state0(s *scanner, c byte) int {
|
||||
if c == '.' {
|
||||
s.step = stateDot
|
||||
return scanContinue
|
||||
}
|
||||
if c == 'e' || c == 'E' {
|
||||
s.step = stateE
|
||||
return scanContinue
|
||||
}
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
|
||||
// stateDot is the state after reading the integer and decimal point in a number,
|
||||
// such as after reading `1.`.
|
||||
func stateDot(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
s.step = stateDot0
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "after decimal point in numeric literal")
|
||||
}
|
||||
|
||||
// stateDot0 is the state after reading the integer, decimal point, and subsequent
|
||||
// digits of a number, such as after reading `3.14`.
|
||||
func stateDot0(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
return scanContinue
|
||||
}
|
||||
if c == 'e' || c == 'E' {
|
||||
s.step = stateE
|
||||
return scanContinue
|
||||
}
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
|
||||
// stateE is the state after reading the mantissa and e in a number,
|
||||
// such as after reading `314e` or `0.314e`.
|
||||
func stateE(s *scanner, c byte) int {
|
||||
if c == '+' || c == '-' {
|
||||
s.step = stateESign
|
||||
return scanContinue
|
||||
}
|
||||
return stateESign(s, c)
|
||||
}
|
||||
|
||||
// stateESign is the state after reading the mantissa, e, and sign in a number,
|
||||
// such as after reading `314e-` or `0.314e+`.
|
||||
func stateESign(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
s.step = stateE0
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in exponent of numeric literal")
|
||||
}
|
||||
|
||||
// stateE0 is the state after reading the mantissa, e, optional sign,
|
||||
// and at least one digit of the exponent in a number,
|
||||
// such as after reading `314e-2` or `0.314e+1` or `3.14e0`.
|
||||
func stateE0(s *scanner, c byte) int {
|
||||
if '0' <= c && c <= '9' {
|
||||
return scanContinue
|
||||
}
|
||||
return stateEndValue(s, c)
|
||||
}
|
||||
|
||||
// stateT is the state after reading `t`.
|
||||
func stateT(s *scanner, c byte) int {
|
||||
if c == 'r' {
|
||||
s.step = stateTr
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal true (expecting 'r')")
|
||||
}
|
||||
|
||||
// stateTr is the state after reading `tr`.
|
||||
func stateTr(s *scanner, c byte) int {
|
||||
if c == 'u' {
|
||||
s.step = stateTru
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal true (expecting 'u')")
|
||||
}
|
||||
|
||||
// stateTru is the state after reading `tru`.
|
||||
func stateTru(s *scanner, c byte) int {
|
||||
if c == 'e' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal true (expecting 'e')")
|
||||
}
|
||||
|
||||
// stateF is the state after reading `f`.
|
||||
func stateF(s *scanner, c byte) int {
|
||||
if c == 'a' {
|
||||
s.step = stateFa
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 'a')")
|
||||
}
|
||||
|
||||
// stateFa is the state after reading `fa`.
|
||||
func stateFa(s *scanner, c byte) int {
|
||||
if c == 'l' {
|
||||
s.step = stateFal
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 'l')")
|
||||
}
|
||||
|
||||
// stateFal is the state after reading `fal`.
|
||||
func stateFal(s *scanner, c byte) int {
|
||||
if c == 's' {
|
||||
s.step = stateFals
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 's')")
|
||||
}
|
||||
|
||||
// stateFals is the state after reading `fals`.
|
||||
func stateFals(s *scanner, c byte) int {
|
||||
if c == 'e' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal false (expecting 'e')")
|
||||
}
|
||||
|
||||
// stateN is the state after reading `n`.
|
||||
func stateN(s *scanner, c byte) int {
|
||||
if c == 'u' {
|
||||
s.step = stateNu
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal null (expecting 'u')")
|
||||
}
|
||||
|
||||
// stateNu is the state after reading `nu`.
|
||||
func stateNu(s *scanner, c byte) int {
|
||||
if c == 'l' {
|
||||
s.step = stateNul
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal null (expecting 'l')")
|
||||
}
|
||||
|
||||
// stateNul is the state after reading `nul`.
|
||||
func stateNul(s *scanner, c byte) int {
|
||||
if c == 'l' {
|
||||
s.step = stateEndValue
|
||||
return scanContinue
|
||||
}
|
||||
return s.error(c, "in literal null (expecting 'l')")
|
||||
}
|
||||
|
||||
// stateError is the state after reaching a syntax error,
|
||||
// such as after reading `[1}` or `5.1.2`.
|
||||
func stateError(s *scanner, c byte) int {
|
||||
return scanError
|
||||
}
|
||||
|
||||
// error records an error and switches to the error state.
|
||||
func (s *scanner) error(c byte, context string) int {
|
||||
s.step = stateError
|
||||
s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
|
||||
return scanError
|
||||
}
|
||||
|
||||
// quoteChar formats c as a quoted character literal
|
||||
func quoteChar(c byte) string {
|
||||
// special cases - different from quoted strings
|
||||
if c == '\'' {
|
||||
return `'\''`
|
||||
}
|
||||
if c == '"' {
|
||||
return `'"'`
|
||||
}
|
||||
|
||||
// use quoted string with different quotation marks
|
||||
s := strconv.Quote(string(c))
|
||||
return "'" + s[1:len(s)-1] + "'"
|
||||
}
|
||||
|
||||
// undo causes the scanner to return scanCode from the next state transition.
|
||||
// This gives callers a simple 1-byte undo mechanism.
|
||||
func (s *scanner) undo(scanCode int) {
|
||||
if s.redo {
|
||||
panic("json: invalid use of scanner")
|
||||
}
|
||||
s.redoCode = scanCode
|
||||
s.redoState = s.step
|
||||
s.step = stateRedo
|
||||
s.redo = true
|
||||
}
|
||||
|
||||
// stateRedo helps implement the scanner's 1-byte undo.
|
||||
func stateRedo(s *scanner, c byte) int {
|
||||
s.redo = false
|
||||
s.step = s.redoState
|
||||
return s.redoCode
|
||||
}
|
484
vendor/github.com/go-jose/go-jose/v3/json/stream.go
generated
vendored
Normal file
484
vendor/github.com/go-jose/go-jose/v3/json/stream.go
generated
vendored
Normal file
@ -0,0 +1,484 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// A Decoder reads and decodes JSON objects from an input stream.
|
||||
type Decoder struct {
|
||||
r io.Reader
|
||||
buf []byte
|
||||
d decodeState
|
||||
scanp int // start of unread data in buf
|
||||
scan scanner
|
||||
err error
|
||||
|
||||
tokenState int
|
||||
tokenStack []int
|
||||
}
|
||||
|
||||
// NewDecoder returns a new decoder that reads from r.
|
||||
//
|
||||
// The decoder introduces its own buffering and may
|
||||
// read data from r beyond the JSON values requested.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
return &Decoder{r: r}
|
||||
}
|
||||
|
||||
// Deprecated: Use `SetNumberType` instead
|
||||
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
|
||||
// Number instead of as a float64.
|
||||
func (dec *Decoder) UseNumber() { dec.d.numberType = UnmarshalJSONNumber }
|
||||
|
||||
// SetNumberType causes the Decoder to unmarshal a number into an interface{} as a
|
||||
// Number, float64 or int64 depending on `t` enum value.
|
||||
func (dec *Decoder) SetNumberType(t NumberUnmarshalType) { dec.d.numberType = t }
|
||||
|
||||
// Decode reads the next JSON-encoded value from its
|
||||
// input and stores it in the value pointed to by v.
|
||||
//
|
||||
// See the documentation for Unmarshal for details about
|
||||
// the conversion of JSON into a Go value.
|
||||
func (dec *Decoder) Decode(v interface{}) error {
|
||||
if dec.err != nil {
|
||||
return dec.err
|
||||
}
|
||||
|
||||
if err := dec.tokenPrepareForDecode(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !dec.tokenValueAllowed() {
|
||||
return &SyntaxError{msg: "not at beginning of value"}
|
||||
}
|
||||
|
||||
// Read whole value into buffer.
|
||||
n, err := dec.readValue()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dec.d.init(dec.buf[dec.scanp : dec.scanp+n])
|
||||
dec.scanp += n
|
||||
|
||||
// Don't save err from unmarshal into dec.err:
|
||||
// the connection is still usable since we read a complete JSON
|
||||
// object from it before the error happened.
|
||||
err = dec.d.unmarshal(v)
|
||||
|
||||
// fixup token streaming state
|
||||
dec.tokenValueEnd()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Buffered returns a reader of the data remaining in the Decoder's
|
||||
// buffer. The reader is valid until the next call to Decode.
|
||||
func (dec *Decoder) Buffered() io.Reader {
|
||||
return bytes.NewReader(dec.buf[dec.scanp:])
|
||||
}
|
||||
|
||||
// readValue reads a JSON value into dec.buf.
|
||||
// It returns the length of the encoding.
|
||||
func (dec *Decoder) readValue() (int, error) {
|
||||
dec.scan.reset()
|
||||
|
||||
scanp := dec.scanp
|
||||
var err error
|
||||
Input:
|
||||
for {
|
||||
// Look in the buffer for a new value.
|
||||
for i, c := range dec.buf[scanp:] {
|
||||
dec.scan.bytes++
|
||||
v := dec.scan.step(&dec.scan, c)
|
||||
if v == scanEnd {
|
||||
scanp += i
|
||||
break Input
|
||||
}
|
||||
// scanEnd is delayed one byte.
|
||||
// We might block trying to get that byte from src,
|
||||
// so instead invent a space byte.
|
||||
if (v == scanEndObject || v == scanEndArray) && dec.scan.step(&dec.scan, ' ') == scanEnd {
|
||||
scanp += i + 1
|
||||
break Input
|
||||
}
|
||||
if v == scanError {
|
||||
dec.err = dec.scan.err
|
||||
return 0, dec.scan.err
|
||||
}
|
||||
}
|
||||
scanp = len(dec.buf)
|
||||
|
||||
// Did the last read have an error?
|
||||
// Delayed until now to allow buffer scan.
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if dec.scan.step(&dec.scan, ' ') == scanEnd {
|
||||
break Input
|
||||
}
|
||||
if nonSpace(dec.buf) {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
}
|
||||
dec.err = err
|
||||
return 0, err
|
||||
}
|
||||
|
||||
n := scanp - dec.scanp
|
||||
err = dec.refill()
|
||||
scanp = dec.scanp + n
|
||||
}
|
||||
return scanp - dec.scanp, nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) refill() error {
|
||||
// Make room to read more into the buffer.
|
||||
// First slide down data already consumed.
|
||||
if dec.scanp > 0 {
|
||||
n := copy(dec.buf, dec.buf[dec.scanp:])
|
||||
dec.buf = dec.buf[:n]
|
||||
dec.scanp = 0
|
||||
}
|
||||
|
||||
// Grow buffer if not large enough.
|
||||
const minRead = 512
|
||||
if cap(dec.buf)-len(dec.buf) < minRead {
|
||||
newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
|
||||
copy(newBuf, dec.buf)
|
||||
dec.buf = newBuf
|
||||
}
|
||||
|
||||
// Read. Delay error for next iteration (after scan).
|
||||
n, err := dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
|
||||
dec.buf = dec.buf[0 : len(dec.buf)+n]
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func nonSpace(b []byte) bool {
|
||||
for _, c := range b {
|
||||
if !isSpace(c) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// An Encoder writes JSON objects to an output stream.
|
||||
type Encoder struct {
|
||||
w io.Writer
|
||||
err error
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{w: w}
|
||||
}
|
||||
|
||||
// Encode writes the JSON encoding of v to the stream,
|
||||
// followed by a newline character.
|
||||
//
|
||||
// See the documentation for Marshal for details about the
|
||||
// conversion of Go values to JSON.
|
||||
func (enc *Encoder) Encode(v interface{}) error {
|
||||
if enc.err != nil {
|
||||
return enc.err
|
||||
}
|
||||
e := newEncodeState()
|
||||
err := e.marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Terminate each value with a newline.
|
||||
// This makes the output look a little nicer
|
||||
// when debugging, and some kind of space
|
||||
// is required if the encoded value was a number,
|
||||
// so that the reader knows there aren't more
|
||||
// digits coming.
|
||||
e.WriteByte('\n')
|
||||
|
||||
if _, err = enc.w.Write(e.Bytes()); err != nil {
|
||||
enc.err = err
|
||||
}
|
||||
encodeStatePool.Put(e)
|
||||
return err
|
||||
}
|
||||
|
||||
// RawMessage is a raw encoded JSON object.
|
||||
// It implements Marshaler and Unmarshaler and can
|
||||
// be used to delay JSON decoding or precompute a JSON encoding.
|
||||
type RawMessage []byte
|
||||
|
||||
// MarshalJSON returns *m as the JSON encoding of m.
|
||||
func (m *RawMessage) MarshalJSON() ([]byte, error) {
|
||||
return *m, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets *m to a copy of data.
|
||||
func (m *RawMessage) UnmarshalJSON(data []byte) error {
|
||||
if m == nil {
|
||||
return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
|
||||
}
|
||||
*m = append((*m)[0:0], data...)
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ Marshaler = (*RawMessage)(nil)
|
||||
var _ Unmarshaler = (*RawMessage)(nil)
|
||||
|
||||
// A Token holds a value of one of these types:
|
||||
//
|
||||
// Delim, for the four JSON delimiters [ ] { }
|
||||
// bool, for JSON booleans
|
||||
// float64, for JSON numbers
|
||||
// Number, for JSON numbers
|
||||
// string, for JSON string literals
|
||||
// nil, for JSON null
|
||||
type Token interface{}
|
||||
|
||||
const (
|
||||
tokenTopValue = iota
|
||||
tokenArrayStart
|
||||
tokenArrayValue
|
||||
tokenArrayComma
|
||||
tokenObjectStart
|
||||
tokenObjectKey
|
||||
tokenObjectColon
|
||||
tokenObjectValue
|
||||
tokenObjectComma
|
||||
)
|
||||
|
||||
// advance tokenstate from a separator state to a value state
|
||||
func (dec *Decoder) tokenPrepareForDecode() error {
|
||||
// Note: Not calling peek before switch, to avoid
|
||||
// putting peek into the standard Decode path.
|
||||
// peek is only called when using the Token API.
|
||||
switch dec.tokenState {
|
||||
case tokenArrayComma:
|
||||
c, err := dec.peek()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c != ',' {
|
||||
return &SyntaxError{"expected comma after array element", 0}
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenArrayValue
|
||||
case tokenObjectColon:
|
||||
c, err := dec.peek()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c != ':' {
|
||||
return &SyntaxError{"expected colon after object key", 0}
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenObjectValue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dec *Decoder) tokenValueAllowed() bool {
|
||||
switch dec.tokenState {
|
||||
case tokenTopValue, tokenArrayStart, tokenArrayValue, tokenObjectValue:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (dec *Decoder) tokenValueEnd() {
|
||||
switch dec.tokenState {
|
||||
case tokenArrayStart, tokenArrayValue:
|
||||
dec.tokenState = tokenArrayComma
|
||||
case tokenObjectValue:
|
||||
dec.tokenState = tokenObjectComma
|
||||
}
|
||||
}
|
||||
|
||||
// A Delim is a JSON array or object delimiter, one of [ ] { or }.
|
||||
type Delim rune
|
||||
|
||||
func (d Delim) String() string {
|
||||
return string(d)
|
||||
}
|
||||
|
||||
// Token returns the next JSON token in the input stream.
|
||||
// At the end of the input stream, Token returns nil, io.EOF.
|
||||
//
|
||||
// Token guarantees that the delimiters [ ] { } it returns are
|
||||
// properly nested and matched: if Token encounters an unexpected
|
||||
// delimiter in the input, it will return an error.
|
||||
//
|
||||
// The input stream consists of basic JSON values—bool, string,
|
||||
// number, and null—along with delimiters [ ] { } of type Delim
|
||||
// to mark the start and end of arrays and objects.
|
||||
// Commas and colons are elided.
|
||||
func (dec *Decoder) Token() (Token, error) {
|
||||
for {
|
||||
c, err := dec.peek()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch c {
|
||||
case '[':
|
||||
if !dec.tokenValueAllowed() {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenStack = append(dec.tokenStack, dec.tokenState)
|
||||
dec.tokenState = tokenArrayStart
|
||||
return Delim('['), nil
|
||||
|
||||
case ']':
|
||||
if dec.tokenState != tokenArrayStart && dec.tokenState != tokenArrayComma {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
|
||||
dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
|
||||
dec.tokenValueEnd()
|
||||
return Delim(']'), nil
|
||||
|
||||
case '{':
|
||||
if !dec.tokenValueAllowed() {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenStack = append(dec.tokenStack, dec.tokenState)
|
||||
dec.tokenState = tokenObjectStart
|
||||
return Delim('{'), nil
|
||||
|
||||
case '}':
|
||||
if dec.tokenState != tokenObjectStart && dec.tokenState != tokenObjectComma {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
|
||||
dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
|
||||
dec.tokenValueEnd()
|
||||
return Delim('}'), nil
|
||||
|
||||
case ':':
|
||||
if dec.tokenState != tokenObjectColon {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenObjectValue
|
||||
continue
|
||||
|
||||
case ',':
|
||||
if dec.tokenState == tokenArrayComma {
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenArrayValue
|
||||
continue
|
||||
}
|
||||
if dec.tokenState == tokenObjectComma {
|
||||
dec.scanp++
|
||||
dec.tokenState = tokenObjectKey
|
||||
continue
|
||||
}
|
||||
return dec.tokenError(c)
|
||||
|
||||
case '"':
|
||||
if dec.tokenState == tokenObjectStart || dec.tokenState == tokenObjectKey {
|
||||
var x string
|
||||
old := dec.tokenState
|
||||
dec.tokenState = tokenTopValue
|
||||
err := dec.Decode(&x)
|
||||
dec.tokenState = old
|
||||
if err != nil {
|
||||
clearOffset(err)
|
||||
return nil, err
|
||||
}
|
||||
dec.tokenState = tokenObjectColon
|
||||
return x, nil
|
||||
}
|
||||
fallthrough
|
||||
|
||||
default:
|
||||
if !dec.tokenValueAllowed() {
|
||||
return dec.tokenError(c)
|
||||
}
|
||||
var x interface{}
|
||||
if err := dec.Decode(&x); err != nil {
|
||||
clearOffset(err)
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func clearOffset(err error) {
|
||||
if s, ok := err.(*SyntaxError); ok {
|
||||
s.Offset = 0
|
||||
}
|
||||
}
|
||||
|
||||
func (dec *Decoder) tokenError(c byte) (Token, error) {
|
||||
var context string
|
||||
switch dec.tokenState {
|
||||
case tokenTopValue:
|
||||
context = " looking for beginning of value"
|
||||
case tokenArrayStart, tokenArrayValue, tokenObjectValue:
|
||||
context = " looking for beginning of value"
|
||||
case tokenArrayComma:
|
||||
context = " after array element"
|
||||
case tokenObjectKey:
|
||||
context = " looking for beginning of object key string"
|
||||
case tokenObjectColon:
|
||||
context = " after object key"
|
||||
case tokenObjectComma:
|
||||
context = " after object key:value pair"
|
||||
}
|
||||
return nil, &SyntaxError{"invalid character " + quoteChar(c) + " " + context, 0}
|
||||
}
|
||||
|
||||
// More reports whether there is another element in the
|
||||
// current array or object being parsed.
|
||||
func (dec *Decoder) More() bool {
|
||||
c, err := dec.peek()
|
||||
return err == nil && c != ']' && c != '}'
|
||||
}
|
||||
|
||||
func (dec *Decoder) peek() (byte, error) {
|
||||
var err error
|
||||
for {
|
||||
for i := dec.scanp; i < len(dec.buf); i++ {
|
||||
c := dec.buf[i]
|
||||
if isSpace(c) {
|
||||
continue
|
||||
}
|
||||
dec.scanp = i
|
||||
return c, nil
|
||||
}
|
||||
// buffer has been scanned, now report any error
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
err = dec.refill()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO
|
||||
|
||||
// EncodeToken writes the given JSON token to the stream.
|
||||
// It returns an error if the delimiters [ ] { } are not properly used.
|
||||
//
|
||||
// EncodeToken does not call Flush, because usually it is part of
|
||||
// a larger operation such as Encode, and those will call Flush when finished.
|
||||
// Callers that create an Encoder and then invoke EncodeToken directly,
|
||||
// without using Encode, need to call Flush when finished to ensure that
|
||||
// the JSON is written to the underlying writer.
|
||||
func (e *Encoder) EncodeToken(t Token) error {
|
||||
...
|
||||
}
|
||||
|
||||
*/
|
44
vendor/github.com/go-jose/go-jose/v3/json/tags.go
generated
vendored
Normal file
44
vendor/github.com/go-jose/go-jose/v3/json/tags.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// tagOptions is the string following a comma in a struct field's "json"
|
||||
// tag, or the empty string. It does not include the leading comma.
|
||||
type tagOptions string
|
||||
|
||||
// parseTag splits a struct field's json tag into its name and
|
||||
// comma-separated options.
|
||||
func parseTag(tag string) (string, tagOptions) {
|
||||
if idx := strings.Index(tag, ","); idx != -1 {
|
||||
return tag[:idx], tagOptions(tag[idx+1:])
|
||||
}
|
||||
return tag, tagOptions("")
|
||||
}
|
||||
|
||||
// Contains reports whether a comma-separated list of options
|
||||
// contains a particular substr flag. substr must be surrounded by a
|
||||
// string boundary or commas.
|
||||
func (o tagOptions) Contains(optionName string) bool {
|
||||
if len(o) == 0 {
|
||||
return false
|
||||
}
|
||||
s := string(o)
|
||||
for s != "" {
|
||||
var next string
|
||||
i := strings.Index(s, ",")
|
||||
if i >= 0 {
|
||||
s, next = s[:i], s[i+1:]
|
||||
}
|
||||
if s == optionName {
|
||||
return true
|
||||
}
|
||||
s = next
|
||||
}
|
||||
return false
|
||||
}
|
295
vendor/github.com/go-jose/go-jose/v3/jwe.go
generated
vendored
Normal file
295
vendor/github.com/go-jose/go-jose/v3/jwe.go
generated
vendored
Normal file
@ -0,0 +1,295 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-jose/go-jose/v3/json"
|
||||
)
|
||||
|
||||
// rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing.
|
||||
type rawJSONWebEncryption struct {
|
||||
Protected *byteBuffer `json:"protected,omitempty"`
|
||||
Unprotected *rawHeader `json:"unprotected,omitempty"`
|
||||
Header *rawHeader `json:"header,omitempty"`
|
||||
Recipients []rawRecipientInfo `json:"recipients,omitempty"`
|
||||
Aad *byteBuffer `json:"aad,omitempty"`
|
||||
EncryptedKey *byteBuffer `json:"encrypted_key,omitempty"`
|
||||
Iv *byteBuffer `json:"iv,omitempty"`
|
||||
Ciphertext *byteBuffer `json:"ciphertext,omitempty"`
|
||||
Tag *byteBuffer `json:"tag,omitempty"`
|
||||
}
|
||||
|
||||
// rawRecipientInfo represents a raw JWE Per-Recipient header JSON object. Used for parsing/serializing.
|
||||
type rawRecipientInfo struct {
|
||||
Header *rawHeader `json:"header,omitempty"`
|
||||
EncryptedKey string `json:"encrypted_key,omitempty"`
|
||||
}
|
||||
|
||||
// JSONWebEncryption represents an encrypted JWE object after parsing.
|
||||
type JSONWebEncryption struct {
|
||||
Header Header
|
||||
protected, unprotected *rawHeader
|
||||
recipients []recipientInfo
|
||||
aad, iv, ciphertext, tag []byte
|
||||
original *rawJSONWebEncryption
|
||||
}
|
||||
|
||||
// recipientInfo represents a raw JWE Per-Recipient header JSON object after parsing.
|
||||
type recipientInfo struct {
|
||||
header *rawHeader
|
||||
encryptedKey []byte
|
||||
}
|
||||
|
||||
// GetAuthData retrieves the (optional) authenticated data attached to the object.
|
||||
func (obj JSONWebEncryption) GetAuthData() []byte {
|
||||
if obj.aad != nil {
|
||||
out := make([]byte, len(obj.aad))
|
||||
copy(out, obj.aad)
|
||||
return out
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get the merged header values
|
||||
func (obj JSONWebEncryption) mergedHeaders(recipient *recipientInfo) rawHeader {
|
||||
out := rawHeader{}
|
||||
out.merge(obj.protected)
|
||||
out.merge(obj.unprotected)
|
||||
|
||||
if recipient != nil {
|
||||
out.merge(recipient.header)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// Get the additional authenticated data from a JWE object.
|
||||
func (obj JSONWebEncryption) computeAuthData() []byte {
|
||||
var protected string
|
||||
|
||||
switch {
|
||||
case obj.original != nil && obj.original.Protected != nil:
|
||||
protected = obj.original.Protected.base64()
|
||||
case obj.protected != nil:
|
||||
protected = base64.RawURLEncoding.EncodeToString(mustSerializeJSON((obj.protected)))
|
||||
default:
|
||||
protected = ""
|
||||
}
|
||||
|
||||
output := []byte(protected)
|
||||
if obj.aad != nil {
|
||||
output = append(output, '.')
|
||||
output = append(output, []byte(base64.RawURLEncoding.EncodeToString(obj.aad))...)
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
// ParseEncrypted parses an encrypted message in compact or JWE JSON Serialization format.
|
||||
func ParseEncrypted(input string) (*JSONWebEncryption, error) {
|
||||
input = stripWhitespace(input)
|
||||
if strings.HasPrefix(input, "{") {
|
||||
return parseEncryptedFull(input)
|
||||
}
|
||||
|
||||
return parseEncryptedCompact(input)
|
||||
}
|
||||
|
||||
// parseEncryptedFull parses a message in compact format.
|
||||
func parseEncryptedFull(input string) (*JSONWebEncryption, error) {
|
||||
var parsed rawJSONWebEncryption
|
||||
err := json.Unmarshal([]byte(input), &parsed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parsed.sanitized()
|
||||
}
|
||||
|
||||
// sanitized produces a cleaned-up JWE object from the raw JSON.
|
||||
func (parsed *rawJSONWebEncryption) sanitized() (*JSONWebEncryption, error) {
|
||||
obj := &JSONWebEncryption{
|
||||
original: parsed,
|
||||
unprotected: parsed.Unprotected,
|
||||
}
|
||||
|
||||
// Check that there is not a nonce in the unprotected headers
|
||||
if parsed.Unprotected != nil {
|
||||
if nonce := parsed.Unprotected.getNonce(); nonce != "" {
|
||||
return nil, ErrUnprotectedNonce
|
||||
}
|
||||
}
|
||||
if parsed.Header != nil {
|
||||
if nonce := parsed.Header.getNonce(); nonce != "" {
|
||||
return nil, ErrUnprotectedNonce
|
||||
}
|
||||
}
|
||||
|
||||
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 {
|
||||
err := json.Unmarshal(parsed.Protected.bytes(), &obj.protected)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid protected header: %s, %s", err, parsed.Protected.base64())
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this must be called _after_ we parse the protected header,
|
||||
// otherwise fields from the protected header will not get picked up.
|
||||
var err error
|
||||
mergedHeaders := obj.mergedHeaders(nil)
|
||||
obj.Header, err = mergedHeaders.sanitized()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: cannot sanitize merged headers: %v (%v)", err, mergedHeaders)
|
||||
}
|
||||
|
||||
if len(parsed.Recipients) == 0 {
|
||||
obj.recipients = []recipientInfo{
|
||||
{
|
||||
header: parsed.Header,
|
||||
encryptedKey: parsed.EncryptedKey.bytes(),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
obj.recipients = make([]recipientInfo, len(parsed.Recipients))
|
||||
for r := range parsed.Recipients {
|
||||
encryptedKey, err := base64URLDecode(parsed.Recipients[r].EncryptedKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check that there is not a nonce in the unprotected header
|
||||
if parsed.Recipients[r].Header != nil && parsed.Recipients[r].Header.getNonce() != "" {
|
||||
return nil, ErrUnprotectedNonce
|
||||
}
|
||||
|
||||
obj.recipients[r].header = parsed.Recipients[r].Header
|
||||
obj.recipients[r].encryptedKey = encryptedKey
|
||||
}
|
||||
}
|
||||
|
||||
for _, recipient := range obj.recipients {
|
||||
headers := obj.mergedHeaders(&recipient)
|
||||
if headers.getAlgorithm() == "" || headers.getEncryption() == "" {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: message is missing alg/enc headers")
|
||||
}
|
||||
}
|
||||
|
||||
obj.iv = parsed.Iv.bytes()
|
||||
obj.ciphertext = parsed.Ciphertext.bytes()
|
||||
obj.tag = parsed.Tag.bytes()
|
||||
obj.aad = parsed.Aad.bytes()
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// parseEncryptedCompact parses a message in compact format.
|
||||
func parseEncryptedCompact(input string) (*JSONWebEncryption, error) {
|
||||
parts := strings.Split(input, ".")
|
||||
if len(parts) != 5 {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts")
|
||||
}
|
||||
|
||||
rawProtected, err := base64URLDecode(parts[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encryptedKey, err := base64URLDecode(parts[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iv, err := base64URLDecode(parts[2])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ciphertext, err := base64URLDecode(parts[3])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tag, err := base64URLDecode(parts[4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
raw := &rawJSONWebEncryption{
|
||||
Protected: newBuffer(rawProtected),
|
||||
EncryptedKey: newBuffer(encryptedKey),
|
||||
Iv: newBuffer(iv),
|
||||
Ciphertext: newBuffer(ciphertext),
|
||||
Tag: newBuffer(tag),
|
||||
}
|
||||
|
||||
return raw.sanitized()
|
||||
}
|
||||
|
||||
// CompactSerialize serializes an object using the compact serialization format.
|
||||
func (obj JSONWebEncryption) CompactSerialize() (string, error) {
|
||||
if len(obj.recipients) != 1 || obj.unprotected != nil ||
|
||||
obj.protected == nil || obj.recipients[0].header != nil {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
|
||||
serializedProtected := mustSerializeJSON(obj.protected)
|
||||
|
||||
return base64JoinWithDots(
|
||||
serializedProtected,
|
||||
obj.recipients[0].encryptedKey,
|
||||
obj.iv,
|
||||
obj.ciphertext,
|
||||
obj.tag,
|
||||
), nil
|
||||
}
|
||||
|
||||
// FullSerialize serializes an object using the full JSON serialization format.
|
||||
func (obj JSONWebEncryption) FullSerialize() string {
|
||||
raw := rawJSONWebEncryption{
|
||||
Unprotected: obj.unprotected,
|
||||
Iv: newBuffer(obj.iv),
|
||||
Ciphertext: newBuffer(obj.ciphertext),
|
||||
EncryptedKey: newBuffer(obj.recipients[0].encryptedKey),
|
||||
Tag: newBuffer(obj.tag),
|
||||
Aad: newBuffer(obj.aad),
|
||||
Recipients: []rawRecipientInfo{},
|
||||
}
|
||||
|
||||
if len(obj.recipients) > 1 {
|
||||
for _, recipient := range obj.recipients {
|
||||
info := rawRecipientInfo{
|
||||
Header: recipient.header,
|
||||
EncryptedKey: base64.RawURLEncoding.EncodeToString(recipient.encryptedKey),
|
||||
}
|
||||
raw.Recipients = append(raw.Recipients, info)
|
||||
}
|
||||
} else {
|
||||
// Use flattened serialization
|
||||
raw.Header = obj.recipients[0].header
|
||||
raw.EncryptedKey = newBuffer(obj.recipients[0].encryptedKey)
|
||||
}
|
||||
|
||||
if obj.protected != nil {
|
||||
raw.Protected = newBuffer(mustSerializeJSON(obj.protected))
|
||||
}
|
||||
|
||||
return string(mustSerializeJSON(raw))
|
||||
}
|
812
vendor/github.com/go-jose/go-jose/v3/jwk.go
generated
vendored
Normal file
812
vendor/github.com/go-jose/go-jose/v3/jwk.go
generated
vendored
Normal file
@ -0,0 +1,812 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-jose/go-jose/v3/json"
|
||||
)
|
||||
|
||||
// rawJSONWebKey represents a public or private key in JWK format, used for parsing/serializing.
|
||||
type rawJSONWebKey struct {
|
||||
Use string `json:"use,omitempty"`
|
||||
Kty string `json:"kty,omitempty"`
|
||||
Kid string `json:"kid,omitempty"`
|
||||
Crv string `json:"crv,omitempty"`
|
||||
Alg string `json:"alg,omitempty"`
|
||||
K *byteBuffer `json:"k,omitempty"`
|
||||
X *byteBuffer `json:"x,omitempty"`
|
||||
Y *byteBuffer `json:"y,omitempty"`
|
||||
N *byteBuffer `json:"n,omitempty"`
|
||||
E *byteBuffer `json:"e,omitempty"`
|
||||
// -- Following fields are only used for private keys --
|
||||
// RSA uses D, P and Q, while ECDSA uses only D. Fields Dp, Dq, and Qi are
|
||||
// completely optional. Therefore for RSA/ECDSA, D != nil is a contract that
|
||||
// we have a private key whereas D == nil means we have only a public key.
|
||||
D *byteBuffer `json:"d,omitempty"`
|
||||
P *byteBuffer `json:"p,omitempty"`
|
||||
Q *byteBuffer `json:"q,omitempty"`
|
||||
Dp *byteBuffer `json:"dp,omitempty"`
|
||||
Dq *byteBuffer `json:"dq,omitempty"`
|
||||
Qi *byteBuffer `json:"qi,omitempty"`
|
||||
// Certificates
|
||||
X5c []string `json:"x5c,omitempty"`
|
||||
X5u string `json:"x5u,omitempty"`
|
||||
X5tSHA1 string `json:"x5t,omitempty"`
|
||||
X5tSHA256 string `json:"x5t#S256,omitempty"`
|
||||
}
|
||||
|
||||
// JSONWebKey represents a public or private key in JWK format. It can be
|
||||
// marshaled into JSON and unmarshaled from JSON.
|
||||
type JSONWebKey struct {
|
||||
// Key is the Go in-memory representation of this key. It must have one
|
||||
// of these types:
|
||||
// - ed25519.PublicKey
|
||||
// - ed25519.PrivateKey
|
||||
// - *ecdsa.PublicKey
|
||||
// - *ecdsa.PrivateKey
|
||||
// - *rsa.PublicKey
|
||||
// - *rsa.PrivateKey
|
||||
// - []byte (a symmetric key)
|
||||
//
|
||||
// When marshaling this JSONWebKey into JSON, the "kty" header parameter
|
||||
// will be automatically set based on the type of this field.
|
||||
Key interface{}
|
||||
// Key identifier, parsed from `kid` header.
|
||||
KeyID string
|
||||
// Key algorithm, parsed from `alg` header.
|
||||
Algorithm string
|
||||
// Key use, parsed from `use` header.
|
||||
Use string
|
||||
|
||||
// X.509 certificate chain, parsed from `x5c` header.
|
||||
Certificates []*x509.Certificate
|
||||
// X.509 certificate URL, parsed from `x5u` header.
|
||||
CertificatesURL *url.URL
|
||||
// X.509 certificate thumbprint (SHA-1), parsed from `x5t` header.
|
||||
CertificateThumbprintSHA1 []byte
|
||||
// X.509 certificate thumbprint (SHA-256), parsed from `x5t#S256` header.
|
||||
CertificateThumbprintSHA256 []byte
|
||||
}
|
||||
|
||||
// MarshalJSON serializes the given key to its JSON representation.
|
||||
func (k JSONWebKey) MarshalJSON() ([]byte, error) {
|
||||
var raw *rawJSONWebKey
|
||||
var err error
|
||||
|
||||
switch key := k.Key.(type) {
|
||||
case ed25519.PublicKey:
|
||||
raw = fromEdPublicKey(key)
|
||||
case *ecdsa.PublicKey:
|
||||
raw, err = fromEcPublicKey(key)
|
||||
case *rsa.PublicKey:
|
||||
raw = fromRsaPublicKey(key)
|
||||
case ed25519.PrivateKey:
|
||||
raw, err = fromEdPrivateKey(key)
|
||||
case *ecdsa.PrivateKey:
|
||||
raw, err = fromEcPrivateKey(key)
|
||||
case *rsa.PrivateKey:
|
||||
raw, err = fromRsaPrivateKey(key)
|
||||
case []byte:
|
||||
raw, err = fromSymmetricKey(key)
|
||||
default:
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
raw.Kid = k.KeyID
|
||||
raw.Alg = k.Algorithm
|
||||
raw.Use = k.Use
|
||||
|
||||
for _, cert := range k.Certificates {
|
||||
raw.X5c = append(raw.X5c, base64.StdEncoding.EncodeToString(cert.Raw))
|
||||
}
|
||||
|
||||
x5tSHA1Len := len(k.CertificateThumbprintSHA1)
|
||||
x5tSHA256Len := len(k.CertificateThumbprintSHA256)
|
||||
if x5tSHA1Len > 0 {
|
||||
if x5tSHA1Len != sha1.Size {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid SHA-1 thumbprint (must be %d bytes, not %d)", sha1.Size, x5tSHA1Len)
|
||||
}
|
||||
raw.X5tSHA1 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA1)
|
||||
}
|
||||
if x5tSHA256Len > 0 {
|
||||
if x5tSHA256Len != sha256.Size {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid SHA-256 thumbprint (must be %d bytes, not %d)", sha256.Size, x5tSHA256Len)
|
||||
}
|
||||
raw.X5tSHA256 = base64.RawURLEncoding.EncodeToString(k.CertificateThumbprintSHA256)
|
||||
}
|
||||
|
||||
// If cert chain is attached (as opposed to being behind a URL), check the
|
||||
// keys thumbprints to make sure they match what is expected. This is to
|
||||
// ensure we don't accidentally produce a JWK with semantically inconsistent
|
||||
// data in the headers.
|
||||
if len(k.Certificates) > 0 {
|
||||
expectedSHA1 := sha1.Sum(k.Certificates[0].Raw)
|
||||
expectedSHA256 := sha256.Sum256(k.Certificates[0].Raw)
|
||||
|
||||
if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(k.CertificateThumbprintSHA1, expectedSHA1[:]) {
|
||||
return nil, errors.New("go-jose/go-jose: invalid SHA-1 thumbprint, does not match cert chain")
|
||||
}
|
||||
if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(k.CertificateThumbprintSHA256, expectedSHA256[:]) {
|
||||
return nil, errors.New("go-jose/go-jose: invalid or SHA-256 thumbprint, does not match cert chain")
|
||||
}
|
||||
}
|
||||
|
||||
if k.CertificatesURL != nil {
|
||||
raw.X5u = k.CertificatesURL.String()
|
||||
}
|
||||
|
||||
return json.Marshal(raw)
|
||||
}
|
||||
|
||||
// UnmarshalJSON reads a key from its JSON representation.
|
||||
func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
|
||||
var raw rawJSONWebKey
|
||||
err = json.Unmarshal(data, &raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
certs, err := parseCertificateChain(raw.X5c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("go-jose/go-jose: failed to unmarshal x5c field: %s", err)
|
||||
}
|
||||
|
||||
var key interface{}
|
||||
var certPub interface{}
|
||||
var keyPub interface{}
|
||||
|
||||
if len(certs) > 0 {
|
||||
// We need to check that leaf public key matches the key embedded in this
|
||||
// JWK, as required by the standard (see RFC 7517, Section 4.7). Otherwise
|
||||
// the JWK parsed could be semantically invalid. Technically, should also
|
||||
// check key usage fields and other extensions on the cert here, but the
|
||||
// standard doesn't exactly explain how they're supposed to map from the
|
||||
// JWK representation to the X.509 extensions.
|
||||
certPub = certs[0].PublicKey
|
||||
}
|
||||
|
||||
switch raw.Kty {
|
||||
case "EC":
|
||||
if raw.D != nil {
|
||||
key, err = raw.ecPrivateKey()
|
||||
if err == nil {
|
||||
keyPub = key.(*ecdsa.PrivateKey).Public()
|
||||
}
|
||||
} else {
|
||||
key, err = raw.ecPublicKey()
|
||||
keyPub = key
|
||||
}
|
||||
case "RSA":
|
||||
if raw.D != nil {
|
||||
key, err = raw.rsaPrivateKey()
|
||||
if err == nil {
|
||||
keyPub = key.(*rsa.PrivateKey).Public()
|
||||
}
|
||||
} else {
|
||||
key, err = raw.rsaPublicKey()
|
||||
keyPub = key
|
||||
}
|
||||
case "oct":
|
||||
if certPub != nil {
|
||||
return errors.New("go-jose/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain")
|
||||
}
|
||||
key, err = raw.symmetricKey()
|
||||
case "OKP":
|
||||
if raw.Crv == "Ed25519" && raw.X != nil {
|
||||
if raw.D != nil {
|
||||
key, err = raw.edPrivateKey()
|
||||
if err == nil {
|
||||
keyPub = key.(ed25519.PrivateKey).Public()
|
||||
}
|
||||
} else {
|
||||
key, err = raw.edPublicKey()
|
||||
keyPub = key
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("go-jose/go-jose: unknown curve %s'", raw.Crv)
|
||||
}
|
||||
default:
|
||||
err = fmt.Errorf("go-jose/go-jose: unknown json web key type '%s'", raw.Kty)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if certPub != nil && keyPub != nil {
|
||||
if !reflect.DeepEqual(certPub, keyPub) {
|
||||
return errors.New("go-jose/go-jose: invalid JWK, public keys in key and x5c fields do not match")
|
||||
}
|
||||
}
|
||||
|
||||
*k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use, Certificates: certs}
|
||||
|
||||
if raw.X5u != "" {
|
||||
k.CertificatesURL, err = url.Parse(raw.X5u)
|
||||
if err != nil {
|
||||
return fmt.Errorf("go-jose/go-jose: invalid JWK, x5u header is invalid URL: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// x5t parameters are base64url-encoded SHA thumbprints
|
||||
// See RFC 7517, Section 4.8, https://tools.ietf.org/html/rfc7517#section-4.8
|
||||
x5tSHA1bytes, err := base64URLDecode(raw.X5tSHA1)
|
||||
if err != nil {
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5t header has invalid encoding")
|
||||
}
|
||||
|
||||
// RFC 7517, Section 4.8 is ambiguous as to whether the digest output should be byte or hex,
|
||||
// for this reason, after base64 decoding, if the size is sha1.Size it's likely that the value is a byte encoded
|
||||
// checksum so we skip this. Otherwise if the checksum was hex encoded we expect a 40 byte sized array so we'll
|
||||
// try to hex decode it. When Marshalling this value we'll always use a base64 encoded version of byte format checksum.
|
||||
if len(x5tSHA1bytes) == 2*sha1.Size {
|
||||
hx, err := hex.DecodeString(string(x5tSHA1bytes))
|
||||
if err != nil {
|
||||
return fmt.Errorf("go-jose/go-jose: invalid JWK, unable to hex decode x5t: %v", err)
|
||||
|
||||
}
|
||||
x5tSHA1bytes = hx
|
||||
}
|
||||
|
||||
k.CertificateThumbprintSHA1 = x5tSHA1bytes
|
||||
|
||||
x5tSHA256bytes, err := base64URLDecode(raw.X5tSHA256)
|
||||
if err != nil {
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header has invalid encoding")
|
||||
}
|
||||
|
||||
if len(x5tSHA256bytes) == 2*sha256.Size {
|
||||
hx256, err := hex.DecodeString(string(x5tSHA256bytes))
|
||||
if err != nil {
|
||||
return fmt.Errorf("go-jose/go-jose: invalid JWK, unable to hex decode x5t#S256: %v", err)
|
||||
}
|
||||
x5tSHA256bytes = hx256
|
||||
}
|
||||
|
||||
k.CertificateThumbprintSHA256 = x5tSHA256bytes
|
||||
|
||||
x5tSHA1Len := len(k.CertificateThumbprintSHA1)
|
||||
x5tSHA256Len := len(k.CertificateThumbprintSHA256)
|
||||
if x5tSHA1Len > 0 && x5tSHA1Len != sha1.Size {
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5t header is of incorrect size")
|
||||
}
|
||||
if x5tSHA256Len > 0 && x5tSHA256Len != sha256.Size {
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5t#S256 header is of incorrect size")
|
||||
}
|
||||
|
||||
// If certificate chain *and* thumbprints are set, verify correctness.
|
||||
if len(k.Certificates) > 0 {
|
||||
leaf := k.Certificates[0]
|
||||
sha1sum := sha1.Sum(leaf.Raw)
|
||||
sha256sum := sha256.Sum256(leaf.Raw)
|
||||
|
||||
if len(k.CertificateThumbprintSHA1) > 0 && !bytes.Equal(sha1sum[:], k.CertificateThumbprintSHA1) {
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5c thumbprint does not match x5t value")
|
||||
}
|
||||
|
||||
if len(k.CertificateThumbprintSHA256) > 0 && !bytes.Equal(sha256sum[:], k.CertificateThumbprintSHA256) {
|
||||
return errors.New("go-jose/go-jose: invalid JWK, x5c thumbprint does not match x5t#S256 value")
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// JSONWebKeySet represents a JWK Set object.
|
||||
type JSONWebKeySet struct {
|
||||
Keys []JSONWebKey `json:"keys"`
|
||||
}
|
||||
|
||||
// Key convenience method returns keys by key ID. Specification states
|
||||
// that a JWK Set "SHOULD" use distinct key IDs, but allows for some
|
||||
// cases where they are not distinct. Hence method returns a slice
|
||||
// of JSONWebKeys.
|
||||
func (s *JSONWebKeySet) Key(kid string) []JSONWebKey {
|
||||
var keys []JSONWebKey
|
||||
for _, key := range s.Keys {
|
||||
if key.KeyID == kid {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
const rsaThumbprintTemplate = `{"e":"%s","kty":"RSA","n":"%s"}`
|
||||
const ecThumbprintTemplate = `{"crv":"%s","kty":"EC","x":"%s","y":"%s"}`
|
||||
const edThumbprintTemplate = `{"crv":"%s","kty":"OKP","x":"%s"}`
|
||||
|
||||
func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) {
|
||||
coordLength := curveSize(curve)
|
||||
crv, err := curveName(curve)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(x.Bytes()) > coordLength || len(y.Bytes()) > coordLength {
|
||||
return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)")
|
||||
}
|
||||
|
||||
return fmt.Sprintf(ecThumbprintTemplate, crv,
|
||||
newFixedSizeBuffer(x.Bytes(), coordLength).base64(),
|
||||
newFixedSizeBuffer(y.Bytes(), coordLength).base64()), nil
|
||||
}
|
||||
|
||||
func rsaThumbprintInput(n *big.Int, e int) (string, error) {
|
||||
return fmt.Sprintf(rsaThumbprintTemplate,
|
||||
newBufferFromInt(uint64(e)).base64(),
|
||||
newBuffer(n.Bytes()).base64()), nil
|
||||
}
|
||||
|
||||
func edThumbprintInput(ed ed25519.PublicKey) (string, error) {
|
||||
crv := "Ed25519"
|
||||
if len(ed) > 32 {
|
||||
return "", errors.New("go-jose/go-jose: invalid elliptic key (too large)")
|
||||
}
|
||||
return fmt.Sprintf(edThumbprintTemplate, crv,
|
||||
newFixedSizeBuffer(ed, 32).base64()), nil
|
||||
}
|
||||
|
||||
// Thumbprint computes the JWK Thumbprint of a key using the
|
||||
// indicated hash algorithm.
|
||||
func (k *JSONWebKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
|
||||
var input string
|
||||
var err error
|
||||
switch key := k.Key.(type) {
|
||||
case ed25519.PublicKey:
|
||||
input, err = edThumbprintInput(key)
|
||||
case *ecdsa.PublicKey:
|
||||
input, err = ecThumbprintInput(key.Curve, key.X, key.Y)
|
||||
case *ecdsa.PrivateKey:
|
||||
input, err = ecThumbprintInput(key.Curve, key.X, key.Y)
|
||||
case *rsa.PublicKey:
|
||||
input, err = rsaThumbprintInput(key.N, key.E)
|
||||
case *rsa.PrivateKey:
|
||||
input, err = rsaThumbprintInput(key.N, key.E)
|
||||
case ed25519.PrivateKey:
|
||||
input, err = edThumbprintInput(ed25519.PublicKey(key[32:]))
|
||||
case OpaqueSigner:
|
||||
return key.Public().Thumbprint(hash)
|
||||
default:
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unknown key type '%s'", reflect.TypeOf(key))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
h := hash.New()
|
||||
_, _ = h.Write([]byte(input))
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
|
||||
// IsPublic returns true if the JWK represents a public key (not symmetric, not private).
|
||||
func (k *JSONWebKey) IsPublic() bool {
|
||||
switch k.Key.(type) {
|
||||
case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Public creates JSONWebKey with corresponding public key if JWK represents asymmetric private key.
|
||||
func (k *JSONWebKey) Public() JSONWebKey {
|
||||
if k.IsPublic() {
|
||||
return *k
|
||||
}
|
||||
ret := *k
|
||||
switch key := k.Key.(type) {
|
||||
case *ecdsa.PrivateKey:
|
||||
ret.Key = key.Public()
|
||||
case *rsa.PrivateKey:
|
||||
ret.Key = key.Public()
|
||||
case ed25519.PrivateKey:
|
||||
ret.Key = key.Public()
|
||||
default:
|
||||
return JSONWebKey{} // returning invalid key
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Valid checks that the key contains the expected parameters.
|
||||
func (k *JSONWebKey) Valid() bool {
|
||||
if k.Key == nil {
|
||||
return false
|
||||
}
|
||||
switch key := k.Key.(type) {
|
||||
case *ecdsa.PublicKey:
|
||||
if key.Curve == nil || key.X == nil || key.Y == nil {
|
||||
return false
|
||||
}
|
||||
case *ecdsa.PrivateKey:
|
||||
if key.Curve == nil || key.X == nil || key.Y == nil || key.D == nil {
|
||||
return false
|
||||
}
|
||||
case *rsa.PublicKey:
|
||||
if key.N == nil || key.E == 0 {
|
||||
return false
|
||||
}
|
||||
case *rsa.PrivateKey:
|
||||
if key.N == nil || key.E == 0 || key.D == nil || len(key.Primes) < 2 {
|
||||
return false
|
||||
}
|
||||
case ed25519.PublicKey:
|
||||
if len(key) != 32 {
|
||||
return false
|
||||
}
|
||||
case ed25519.PrivateKey:
|
||||
if len(key) != 64 {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (key rawJSONWebKey) rsaPublicKey() (*rsa.PublicKey, error) {
|
||||
if key.N == nil || key.E == nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key, missing n/e values")
|
||||
}
|
||||
|
||||
return &rsa.PublicKey{
|
||||
N: key.N.bigInt(),
|
||||
E: key.E.toInt(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func fromEdPublicKey(pub ed25519.PublicKey) *rawJSONWebKey {
|
||||
return &rawJSONWebKey{
|
||||
Kty: "OKP",
|
||||
Crv: "Ed25519",
|
||||
X: newBuffer(pub),
|
||||
}
|
||||
}
|
||||
|
||||
func fromRsaPublicKey(pub *rsa.PublicKey) *rawJSONWebKey {
|
||||
return &rawJSONWebKey{
|
||||
Kty: "RSA",
|
||||
N: newBuffer(pub.N.Bytes()),
|
||||
E: newBufferFromInt(uint64(pub.E)),
|
||||
}
|
||||
}
|
||||
|
||||
func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) {
|
||||
var curve elliptic.Curve
|
||||
switch key.Crv {
|
||||
case "P-256":
|
||||
curve = elliptic.P256()
|
||||
case "P-384":
|
||||
curve = elliptic.P384()
|
||||
case "P-521":
|
||||
curve = elliptic.P521()
|
||||
default:
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv)
|
||||
}
|
||||
|
||||
if key.X == nil || key.Y == nil {
|
||||
return nil, errors.New("go-jose/go-jose: invalid EC key, missing x/y values")
|
||||
}
|
||||
|
||||
// The length of this octet string MUST be the full size of a coordinate for
|
||||
// the curve specified in the "crv" parameter.
|
||||
// https://tools.ietf.org/html/rfc7518#section-6.2.1.2
|
||||
if curveSize(curve) != len(key.X.data) {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for x")
|
||||
}
|
||||
|
||||
if curveSize(curve) != len(key.Y.data) {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for y")
|
||||
}
|
||||
|
||||
x := key.X.bigInt()
|
||||
y := key.Y.bigInt()
|
||||
|
||||
if !curve.IsOnCurve(x, y) {
|
||||
return nil, errors.New("go-jose/go-jose: invalid EC key, X/Y are not on declared curve")
|
||||
}
|
||||
|
||||
return &ecdsa.PublicKey{
|
||||
Curve: curve,
|
||||
X: x,
|
||||
Y: y,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func fromEcPublicKey(pub *ecdsa.PublicKey) (*rawJSONWebKey, error) {
|
||||
if pub == nil || pub.X == nil || pub.Y == nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC key (nil, or X/Y missing)")
|
||||
}
|
||||
|
||||
name, err := curveName(pub.Curve)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
size := curveSize(pub.Curve)
|
||||
|
||||
xBytes := pub.X.Bytes()
|
||||
yBytes := pub.Y.Bytes()
|
||||
|
||||
if len(xBytes) > size || len(yBytes) > size {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC key (X/Y too large)")
|
||||
}
|
||||
|
||||
key := &rawJSONWebKey{
|
||||
Kty: "EC",
|
||||
Crv: name,
|
||||
X: newFixedSizeBuffer(xBytes, size),
|
||||
Y: newFixedSizeBuffer(yBytes, size),
|
||||
}
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func (key rawJSONWebKey) edPrivateKey() (ed25519.PrivateKey, error) {
|
||||
var missing []string
|
||||
switch {
|
||||
case key.D == nil:
|
||||
missing = append(missing, "D")
|
||||
case key.X == nil:
|
||||
missing = append(missing, "X")
|
||||
}
|
||||
|
||||
if len(missing) > 0 {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid Ed25519 private key, missing %s value(s)", strings.Join(missing, ", "))
|
||||
}
|
||||
|
||||
privateKey := make([]byte, ed25519.PrivateKeySize)
|
||||
copy(privateKey[0:32], key.D.bytes())
|
||||
copy(privateKey[32:], key.X.bytes())
|
||||
rv := ed25519.PrivateKey(privateKey)
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
func (key rawJSONWebKey) edPublicKey() (ed25519.PublicKey, error) {
|
||||
if key.X == nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid Ed key, missing x value")
|
||||
}
|
||||
publicKey := make([]byte, ed25519.PublicKeySize)
|
||||
copy(publicKey[0:32], key.X.bytes())
|
||||
rv := ed25519.PublicKey(publicKey)
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
|
||||
var missing []string
|
||||
switch {
|
||||
case key.N == nil:
|
||||
missing = append(missing, "N")
|
||||
case key.E == nil:
|
||||
missing = append(missing, "E")
|
||||
case key.D == nil:
|
||||
missing = append(missing, "D")
|
||||
case key.P == nil:
|
||||
missing = append(missing, "P")
|
||||
case key.Q == nil:
|
||||
missing = append(missing, "Q")
|
||||
}
|
||||
|
||||
if len(missing) > 0 {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", "))
|
||||
}
|
||||
|
||||
rv := &rsa.PrivateKey{
|
||||
PublicKey: rsa.PublicKey{
|
||||
N: key.N.bigInt(),
|
||||
E: key.E.toInt(),
|
||||
},
|
||||
D: key.D.bigInt(),
|
||||
Primes: []*big.Int{
|
||||
key.P.bigInt(),
|
||||
key.Q.bigInt(),
|
||||
},
|
||||
}
|
||||
|
||||
if key.Dp != nil {
|
||||
rv.Precomputed.Dp = key.Dp.bigInt()
|
||||
}
|
||||
if key.Dq != nil {
|
||||
rv.Precomputed.Dq = key.Dq.bigInt()
|
||||
}
|
||||
if key.Qi != nil {
|
||||
rv.Precomputed.Qinv = key.Qi.bigInt()
|
||||
}
|
||||
|
||||
err := rv.Validate()
|
||||
return rv, err
|
||||
}
|
||||
|
||||
func fromEdPrivateKey(ed ed25519.PrivateKey) (*rawJSONWebKey, error) {
|
||||
raw := fromEdPublicKey(ed25519.PublicKey(ed[32:]))
|
||||
|
||||
raw.D = newBuffer(ed[0:32])
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
func fromRsaPrivateKey(rsa *rsa.PrivateKey) (*rawJSONWebKey, error) {
|
||||
if len(rsa.Primes) != 2 {
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
|
||||
raw := fromRsaPublicKey(&rsa.PublicKey)
|
||||
|
||||
raw.D = newBuffer(rsa.D.Bytes())
|
||||
raw.P = newBuffer(rsa.Primes[0].Bytes())
|
||||
raw.Q = newBuffer(rsa.Primes[1].Bytes())
|
||||
|
||||
if rsa.Precomputed.Dp != nil {
|
||||
raw.Dp = newBuffer(rsa.Precomputed.Dp.Bytes())
|
||||
}
|
||||
if rsa.Precomputed.Dq != nil {
|
||||
raw.Dq = newBuffer(rsa.Precomputed.Dq.Bytes())
|
||||
}
|
||||
if rsa.Precomputed.Qinv != nil {
|
||||
raw.Qi = newBuffer(rsa.Precomputed.Qinv.Bytes())
|
||||
}
|
||||
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
func (key rawJSONWebKey) ecPrivateKey() (*ecdsa.PrivateKey, error) {
|
||||
var curve elliptic.Curve
|
||||
switch key.Crv {
|
||||
case "P-256":
|
||||
curve = elliptic.P256()
|
||||
case "P-384":
|
||||
curve = elliptic.P384()
|
||||
case "P-521":
|
||||
curve = elliptic.P521()
|
||||
default:
|
||||
return nil, fmt.Errorf("go-jose/go-jose: unsupported elliptic curve '%s'", key.Crv)
|
||||
}
|
||||
|
||||
if key.X == nil || key.Y == nil || key.D == nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, missing x/y/d values")
|
||||
}
|
||||
|
||||
// The length of this octet string MUST be the full size of a coordinate for
|
||||
// the curve specified in the "crv" parameter.
|
||||
// https://tools.ietf.org/html/rfc7518#section-6.2.1.2
|
||||
if curveSize(curve) != len(key.X.data) {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for x")
|
||||
}
|
||||
|
||||
if curveSize(curve) != len(key.Y.data) {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for y")
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc7518#section-6.2.2.1
|
||||
if dSize(curve) != len(key.D.data) {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for d")
|
||||
}
|
||||
|
||||
x := key.X.bigInt()
|
||||
y := key.Y.bigInt()
|
||||
|
||||
if !curve.IsOnCurve(x, y) {
|
||||
return nil, errors.New("go-jose/go-jose: invalid EC key, X/Y are not on declared curve")
|
||||
}
|
||||
|
||||
return &ecdsa.PrivateKey{
|
||||
PublicKey: ecdsa.PublicKey{
|
||||
Curve: curve,
|
||||
X: x,
|
||||
Y: y,
|
||||
},
|
||||
D: key.D.bigInt(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func fromEcPrivateKey(ec *ecdsa.PrivateKey) (*rawJSONWebKey, error) {
|
||||
raw, err := fromEcPublicKey(&ec.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ec.D == nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key")
|
||||
}
|
||||
|
||||
raw.D = newFixedSizeBuffer(ec.D.Bytes(), dSize(ec.PublicKey.Curve))
|
||||
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
// dSize returns the size in octets for the "d" member of an elliptic curve
|
||||
// private key.
|
||||
// The length of this octet string MUST be ceiling(log-base-2(n)/8)
|
||||
// octets (where n is the order of the curve).
|
||||
// https://tools.ietf.org/html/rfc7518#section-6.2.2.1
|
||||
func dSize(curve elliptic.Curve) int {
|
||||
order := curve.Params().P
|
||||
bitLen := order.BitLen()
|
||||
size := bitLen / 8
|
||||
if bitLen%8 != 0 {
|
||||
size++
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func fromSymmetricKey(key []byte) (*rawJSONWebKey, error) {
|
||||
return &rawJSONWebKey{
|
||||
Kty: "oct",
|
||||
K: newBuffer(key),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (key rawJSONWebKey) symmetricKey() ([]byte, error) {
|
||||
if key.K == nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid OCT (symmetric) key, missing k value")
|
||||
}
|
||||
return key.K.bytes(), nil
|
||||
}
|
||||
|
||||
func tryJWKS(key interface{}, headers ...Header) interface{} {
|
||||
var jwks JSONWebKeySet
|
||||
|
||||
switch jwksType := key.(type) {
|
||||
case *JSONWebKeySet:
|
||||
jwks = *jwksType
|
||||
case JSONWebKeySet:
|
||||
jwks = jwksType
|
||||
default:
|
||||
return key
|
||||
}
|
||||
|
||||
var kid string
|
||||
for _, header := range headers {
|
||||
if header.KeyID != "" {
|
||||
kid = header.KeyID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if kid == "" {
|
||||
return key
|
||||
}
|
||||
|
||||
keys := jwks.Key(kid)
|
||||
if len(keys) == 0 {
|
||||
return key
|
||||
}
|
||||
|
||||
return keys[0].Key
|
||||
}
|
369
vendor/github.com/go-jose/go-jose/v3/jws.go
generated
vendored
Normal file
369
vendor/github.com/go-jose/go-jose/v3/jws.go
generated
vendored
Normal file
@ -0,0 +1,369 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-jose/go-jose/v3/json"
|
||||
)
|
||||
|
||||
// rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing.
|
||||
type rawJSONWebSignature struct {
|
||||
Payload *byteBuffer `json:"payload,omitempty"`
|
||||
Signatures []rawSignatureInfo `json:"signatures,omitempty"`
|
||||
Protected *byteBuffer `json:"protected,omitempty"`
|
||||
Header *rawHeader `json:"header,omitempty"`
|
||||
Signature *byteBuffer `json:"signature,omitempty"`
|
||||
}
|
||||
|
||||
// rawSignatureInfo represents a single JWS signature over the JWS payload and protected header.
|
||||
type rawSignatureInfo struct {
|
||||
Protected *byteBuffer `json:"protected,omitempty"`
|
||||
Header *rawHeader `json:"header,omitempty"`
|
||||
Signature *byteBuffer `json:"signature,omitempty"`
|
||||
}
|
||||
|
||||
// JSONWebSignature represents a signed JWS object after parsing.
|
||||
type JSONWebSignature struct {
|
||||
payload []byte
|
||||
// Signatures attached to this object (may be more than one for multi-sig).
|
||||
// Be careful about accessing these directly, prefer to use Verify() or
|
||||
// VerifyMulti() to ensure that the data you're getting is verified.
|
||||
Signatures []Signature
|
||||
}
|
||||
|
||||
// Signature represents a single signature over the JWS payload and protected header.
|
||||
type Signature struct {
|
||||
// Merged header fields. Contains both protected and unprotected header
|
||||
// values. Prefer using Protected and Unprotected fields instead of this.
|
||||
// Values in this header may or may not have been signed and in general
|
||||
// should not be trusted.
|
||||
Header Header
|
||||
|
||||
// Protected header. Values in this header were signed and
|
||||
// will be verified as part of the signature verification process.
|
||||
Protected Header
|
||||
|
||||
// Unprotected header. Values in this header were not signed
|
||||
// and in general should not be trusted.
|
||||
Unprotected Header
|
||||
|
||||
// The actual signature value
|
||||
Signature []byte
|
||||
|
||||
protected *rawHeader
|
||||
header *rawHeader
|
||||
original *rawSignatureInfo
|
||||
}
|
||||
|
||||
// ParseSigned parses a signed message in compact or JWS JSON Serialization format.
|
||||
func ParseSigned(signature string) (*JSONWebSignature, error) {
|
||||
signature = stripWhitespace(signature)
|
||||
if strings.HasPrefix(signature, "{") {
|
||||
return parseSignedFull(signature)
|
||||
}
|
||||
|
||||
return parseSignedCompact(signature, nil)
|
||||
}
|
||||
|
||||
// ParseDetached parses a signed message in compact serialization format with detached payload.
|
||||
func ParseDetached(signature string, payload []byte) (*JSONWebSignature, error) {
|
||||
if payload == nil {
|
||||
return nil, errors.New("go-jose/go-jose: nil payload")
|
||||
}
|
||||
return parseSignedCompact(stripWhitespace(signature), payload)
|
||||
}
|
||||
|
||||
// Get a header value
|
||||
func (sig Signature) mergedHeaders() rawHeader {
|
||||
out := rawHeader{}
|
||||
out.merge(sig.protected)
|
||||
out.merge(sig.header)
|
||||
return out
|
||||
}
|
||||
|
||||
// Compute data to be signed
|
||||
func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature) ([]byte, error) {
|
||||
var authData bytes.Buffer
|
||||
|
||||
protectedHeader := new(rawHeader)
|
||||
|
||||
if signature.original != nil && signature.original.Protected != nil {
|
||||
if err := json.Unmarshal(signature.original.Protected.bytes(), protectedHeader); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authData.WriteString(signature.original.Protected.base64())
|
||||
} else if signature.protected != nil {
|
||||
protectedHeader = signature.protected
|
||||
authData.WriteString(base64.RawURLEncoding.EncodeToString(mustSerializeJSON(protectedHeader)))
|
||||
}
|
||||
|
||||
needsBase64 := true
|
||||
|
||||
if protectedHeader != nil {
|
||||
var err error
|
||||
if needsBase64, err = protectedHeader.getB64(); err != nil {
|
||||
needsBase64 = true
|
||||
}
|
||||
}
|
||||
|
||||
authData.WriteByte('.')
|
||||
|
||||
if needsBase64 {
|
||||
authData.WriteString(base64.RawURLEncoding.EncodeToString(payload))
|
||||
} else {
|
||||
authData.Write(payload)
|
||||
}
|
||||
|
||||
return authData.Bytes(), nil
|
||||
}
|
||||
|
||||
// parseSignedFull parses a message in full format.
|
||||
func parseSignedFull(input string) (*JSONWebSignature, error) {
|
||||
var parsed rawJSONWebSignature
|
||||
err := json.Unmarshal([]byte(input), &parsed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parsed.sanitized()
|
||||
}
|
||||
|
||||
// sanitized produces a cleaned-up JWS object from the raw JSON.
|
||||
func (parsed *rawJSONWebSignature) sanitized() (*JSONWebSignature, error) {
|
||||
if parsed.Payload == nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: missing payload in JWS message")
|
||||
}
|
||||
|
||||
obj := &JSONWebSignature{
|
||||
payload: parsed.Payload.bytes(),
|
||||
Signatures: make([]Signature, len(parsed.Signatures)),
|
||||
}
|
||||
|
||||
if len(parsed.Signatures) == 0 {
|
||||
// No signatures array, must be flattened serialization
|
||||
signature := Signature{}
|
||||
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 {
|
||||
signature.protected = &rawHeader{}
|
||||
err := json.Unmarshal(parsed.Protected.bytes(), signature.protected)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Check that there is not a nonce in the unprotected header
|
||||
if parsed.Header != nil && parsed.Header.getNonce() != "" {
|
||||
return nil, ErrUnprotectedNonce
|
||||
}
|
||||
|
||||
signature.header = parsed.Header
|
||||
signature.Signature = parsed.Signature.bytes()
|
||||
// Make a fake "original" rawSignatureInfo to store the unprocessed
|
||||
// Protected header. This is necessary because the Protected header can
|
||||
// contain arbitrary fields not registered as part of the spec. See
|
||||
// https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-4
|
||||
// If we unmarshal Protected into a rawHeader with its explicit list of fields,
|
||||
// we cannot marshal losslessly. So we have to keep around the original bytes.
|
||||
// This is used in computeAuthData, which will first attempt to use
|
||||
// the original bytes of a protected header, and fall back on marshaling the
|
||||
// header struct only if those bytes are not available.
|
||||
signature.original = &rawSignatureInfo{
|
||||
Protected: parsed.Protected,
|
||||
Header: parsed.Header,
|
||||
Signature: parsed.Signature,
|
||||
}
|
||||
|
||||
var err error
|
||||
signature.Header, err = signature.mergedHeaders().sanitized()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if signature.header != nil {
|
||||
signature.Unprotected, err = signature.header.sanitized()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if signature.protected != nil {
|
||||
signature.Protected, err = signature.protected.sanitized()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
|
||||
jwk := signature.Header.JSONWebKey
|
||||
if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) {
|
||||
return nil, errors.New("go-jose/go-jose: invalid embedded jwk, must be public key")
|
||||
}
|
||||
|
||||
obj.Signatures = append(obj.Signatures, signature)
|
||||
}
|
||||
|
||||
for i, sig := range parsed.Signatures {
|
||||
if sig.Protected != nil && len(sig.Protected.bytes()) > 0 {
|
||||
obj.Signatures[i].protected = &rawHeader{}
|
||||
err := json.Unmarshal(sig.Protected.bytes(), obj.Signatures[i].protected)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Check that there is not a nonce in the unprotected header
|
||||
if sig.Header != nil && sig.Header.getNonce() != "" {
|
||||
return nil, ErrUnprotectedNonce
|
||||
}
|
||||
|
||||
var err error
|
||||
obj.Signatures[i].Header, err = obj.Signatures[i].mergedHeaders().sanitized()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if obj.Signatures[i].header != nil {
|
||||
obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if obj.Signatures[i].protected != nil {
|
||||
obj.Signatures[i].Protected, err = obj.Signatures[i].protected.sanitized()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
obj.Signatures[i].Signature = sig.Signature.bytes()
|
||||
|
||||
// As per RFC 7515 Section 4.1.3, only public keys are allowed to be embedded.
|
||||
jwk := obj.Signatures[i].Header.JSONWebKey
|
||||
if jwk != nil && (!jwk.Valid() || !jwk.IsPublic()) {
|
||||
return nil, errors.New("go-jose/go-jose: invalid embedded jwk, must be public key")
|
||||
}
|
||||
|
||||
// Copy value of sig
|
||||
original := sig
|
||||
|
||||
obj.Signatures[i].header = sig.Header
|
||||
obj.Signatures[i].original = &original
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// parseSignedCompact parses a message in compact format.
|
||||
func parseSignedCompact(input string, payload []byte) (*JSONWebSignature, error) {
|
||||
parts := strings.Split(input, ".")
|
||||
if len(parts) != 3 {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts")
|
||||
}
|
||||
|
||||
if parts[1] != "" && payload != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: payload is not detached")
|
||||
}
|
||||
|
||||
rawProtected, err := base64URLDecode(parts[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if payload == nil {
|
||||
payload, err = base64URLDecode(parts[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
signature, err := base64URLDecode(parts[2])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
raw := &rawJSONWebSignature{
|
||||
Payload: newBuffer(payload),
|
||||
Protected: newBuffer(rawProtected),
|
||||
Signature: newBuffer(signature),
|
||||
}
|
||||
return raw.sanitized()
|
||||
}
|
||||
|
||||
func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
|
||||
if len(obj.Signatures) != 1 || obj.Signatures[0].header != nil || obj.Signatures[0].protected == nil {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
|
||||
serializedProtected := mustSerializeJSON(obj.Signatures[0].protected)
|
||||
|
||||
var payload []byte
|
||||
if !detached {
|
||||
payload = obj.payload
|
||||
}
|
||||
|
||||
return base64JoinWithDots(
|
||||
serializedProtected,
|
||||
payload,
|
||||
obj.Signatures[0].Signature,
|
||||
), nil
|
||||
}
|
||||
|
||||
// CompactSerialize serializes an object using the compact serialization format.
|
||||
func (obj JSONWebSignature) CompactSerialize() (string, error) {
|
||||
return obj.compactSerialize(false)
|
||||
}
|
||||
|
||||
// DetachedCompactSerialize serializes an object using the compact serialization format with detached payload.
|
||||
func (obj JSONWebSignature) DetachedCompactSerialize() (string, error) {
|
||||
return obj.compactSerialize(true)
|
||||
}
|
||||
|
||||
// FullSerialize serializes an object using the full JSON serialization format.
|
||||
func (obj JSONWebSignature) FullSerialize() string {
|
||||
raw := rawJSONWebSignature{
|
||||
Payload: newBuffer(obj.payload),
|
||||
}
|
||||
|
||||
if len(obj.Signatures) == 1 {
|
||||
if obj.Signatures[0].protected != nil {
|
||||
serializedProtected := mustSerializeJSON(obj.Signatures[0].protected)
|
||||
raw.Protected = newBuffer(serializedProtected)
|
||||
}
|
||||
raw.Header = obj.Signatures[0].header
|
||||
raw.Signature = newBuffer(obj.Signatures[0].Signature)
|
||||
} else {
|
||||
raw.Signatures = make([]rawSignatureInfo, len(obj.Signatures))
|
||||
for i, signature := range obj.Signatures {
|
||||
raw.Signatures[i] = rawSignatureInfo{
|
||||
Header: signature.header,
|
||||
Signature: newBuffer(signature.Signature),
|
||||
}
|
||||
|
||||
if signature.protected != nil {
|
||||
raw.Signatures[i].Protected = newBuffer(mustSerializeJSON(signature.protected))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string(mustSerializeJSON(raw))
|
||||
}
|
144
vendor/github.com/go-jose/go-jose/v3/opaque.go
generated
vendored
Normal file
144
vendor/github.com/go-jose/go-jose/v3/opaque.go
generated
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
/*-
|
||||
* Copyright 2018 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
// OpaqueSigner is an interface that supports signing payloads with opaque
|
||||
// private key(s). Private key operations performed by implementers may, for
|
||||
// example, occur in a hardware module. An OpaqueSigner may rotate signing keys
|
||||
// transparently to the user of this interface.
|
||||
type OpaqueSigner interface {
|
||||
// Public returns the public key of the current signing key.
|
||||
Public() *JSONWebKey
|
||||
// Algs returns a list of supported signing algorithms.
|
||||
Algs() []SignatureAlgorithm
|
||||
// SignPayload signs a payload with the current signing key using the given
|
||||
// algorithm.
|
||||
SignPayload(payload []byte, alg SignatureAlgorithm) ([]byte, error)
|
||||
}
|
||||
|
||||
type opaqueSigner struct {
|
||||
signer OpaqueSigner
|
||||
}
|
||||
|
||||
func newOpaqueSigner(alg SignatureAlgorithm, signer OpaqueSigner) (recipientSigInfo, error) {
|
||||
var algSupported bool
|
||||
for _, salg := range signer.Algs() {
|
||||
if alg == salg {
|
||||
algSupported = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !algSupported {
|
||||
return recipientSigInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
return recipientSigInfo{
|
||||
sigAlg: alg,
|
||||
publicKey: signer.Public,
|
||||
signer: &opaqueSigner{
|
||||
signer: signer,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (o *opaqueSigner) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
||||
out, err := o.signer.SignPayload(payload, alg)
|
||||
if err != nil {
|
||||
return Signature{}, err
|
||||
}
|
||||
|
||||
return Signature{
|
||||
Signature: out,
|
||||
protected: &rawHeader{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// OpaqueVerifier is an interface that supports verifying payloads with opaque
|
||||
// public key(s). An OpaqueSigner may rotate signing keys transparently to the
|
||||
// user of this interface.
|
||||
type OpaqueVerifier interface {
|
||||
VerifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error
|
||||
}
|
||||
|
||||
type opaqueVerifier struct {
|
||||
verifier OpaqueVerifier
|
||||
}
|
||||
|
||||
func (o *opaqueVerifier) verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error {
|
||||
return o.verifier.VerifyPayload(payload, signature, alg)
|
||||
}
|
||||
|
||||
// OpaqueKeyEncrypter is an interface that supports encrypting keys with an opaque key.
|
||||
type OpaqueKeyEncrypter interface {
|
||||
// KeyID returns the kid
|
||||
KeyID() string
|
||||
// Algs returns a list of supported key encryption algorithms.
|
||||
Algs() []KeyAlgorithm
|
||||
// encryptKey encrypts the CEK using the given algorithm.
|
||||
encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error)
|
||||
}
|
||||
|
||||
type opaqueKeyEncrypter struct {
|
||||
encrypter OpaqueKeyEncrypter
|
||||
}
|
||||
|
||||
func newOpaqueKeyEncrypter(alg KeyAlgorithm, encrypter OpaqueKeyEncrypter) (recipientKeyInfo, error) {
|
||||
var algSupported bool
|
||||
for _, salg := range encrypter.Algs() {
|
||||
if alg == salg {
|
||||
algSupported = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !algSupported {
|
||||
return recipientKeyInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
return recipientKeyInfo{
|
||||
keyID: encrypter.KeyID(),
|
||||
keyAlg: alg,
|
||||
keyEncrypter: &opaqueKeyEncrypter{
|
||||
encrypter: encrypter,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (oke *opaqueKeyEncrypter) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
|
||||
return oke.encrypter.encryptKey(cek, alg)
|
||||
}
|
||||
|
||||
// OpaqueKeyDecrypter is an interface that supports decrypting keys with an opaque key.
|
||||
type OpaqueKeyDecrypter interface {
|
||||
DecryptKey(encryptedKey []byte, header Header) ([]byte, error)
|
||||
}
|
||||
|
||||
type opaqueKeyDecrypter struct {
|
||||
decrypter OpaqueKeyDecrypter
|
||||
}
|
||||
|
||||
func (okd *opaqueKeyDecrypter) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
||||
mergedHeaders := rawHeader{}
|
||||
mergedHeaders.merge(&headers)
|
||||
mergedHeaders.merge(recipient.header)
|
||||
|
||||
header, err := mergedHeaders.sanitized()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return okd.decrypter.DecryptKey(recipient.encryptedKey, header)
|
||||
}
|
525
vendor/github.com/go-jose/go-jose/v3/shared.go
generated
vendored
Normal file
525
vendor/github.com/go-jose/go-jose/v3/shared.go
generated
vendored
Normal file
@ -0,0 +1,525 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-jose/go-jose/v3/json"
|
||||
)
|
||||
|
||||
// KeyAlgorithm represents a key management algorithm.
|
||||
type KeyAlgorithm string
|
||||
|
||||
// SignatureAlgorithm represents a signature (or MAC) algorithm.
|
||||
type SignatureAlgorithm string
|
||||
|
||||
// ContentEncryption represents a content encryption algorithm.
|
||||
type ContentEncryption string
|
||||
|
||||
// CompressionAlgorithm represents an algorithm used for plaintext compression.
|
||||
type CompressionAlgorithm string
|
||||
|
||||
// ContentType represents type of the contained data.
|
||||
type ContentType string
|
||||
|
||||
var (
|
||||
// ErrCryptoFailure represents an error in cryptographic primitive. This
|
||||
// occurs when, for example, a message had an invalid authentication tag or
|
||||
// could not be decrypted.
|
||||
ErrCryptoFailure = errors.New("go-jose/go-jose: error in cryptographic primitive")
|
||||
|
||||
// ErrUnsupportedAlgorithm indicates that a selected algorithm is not
|
||||
// supported. This occurs when trying to instantiate an encrypter for an
|
||||
// algorithm that is not yet implemented.
|
||||
ErrUnsupportedAlgorithm = errors.New("go-jose/go-jose: unknown/unsupported algorithm")
|
||||
|
||||
// ErrUnsupportedKeyType indicates that the given key type/format is not
|
||||
// supported. This occurs when trying to instantiate an encrypter and passing
|
||||
// it a key of an unrecognized type or with unsupported parameters, such as
|
||||
// an RSA private key with more than two primes.
|
||||
ErrUnsupportedKeyType = errors.New("go-jose/go-jose: unsupported key type/format")
|
||||
|
||||
// ErrInvalidKeySize indicates that the given key is not the correct size
|
||||
// for the selected algorithm. This can occur, for example, when trying to
|
||||
// encrypt with AES-256 but passing only a 128-bit key as input.
|
||||
ErrInvalidKeySize = errors.New("go-jose/go-jose: invalid key size for algorithm")
|
||||
|
||||
// ErrNotSupported serialization of object is not supported. This occurs when
|
||||
// trying to compact-serialize an object which can't be represented in
|
||||
// compact form.
|
||||
ErrNotSupported = errors.New("go-jose/go-jose: compact serialization not supported for object")
|
||||
|
||||
// ErrUnprotectedNonce indicates that while parsing a JWS or JWE object, a
|
||||
// nonce header parameter was included in an unprotected header object.
|
||||
ErrUnprotectedNonce = errors.New("go-jose/go-jose: Nonce parameter included in unprotected header")
|
||||
)
|
||||
|
||||
// Key management algorithms
|
||||
const (
|
||||
ED25519 = KeyAlgorithm("ED25519")
|
||||
RSA1_5 = KeyAlgorithm("RSA1_5") // RSA-PKCS1v1.5
|
||||
RSA_OAEP = KeyAlgorithm("RSA-OAEP") // RSA-OAEP-SHA1
|
||||
RSA_OAEP_256 = KeyAlgorithm("RSA-OAEP-256") // RSA-OAEP-SHA256
|
||||
A128KW = KeyAlgorithm("A128KW") // AES key wrap (128)
|
||||
A192KW = KeyAlgorithm("A192KW") // AES key wrap (192)
|
||||
A256KW = KeyAlgorithm("A256KW") // AES key wrap (256)
|
||||
DIRECT = KeyAlgorithm("dir") // Direct encryption
|
||||
ECDH_ES = KeyAlgorithm("ECDH-ES") // ECDH-ES
|
||||
ECDH_ES_A128KW = KeyAlgorithm("ECDH-ES+A128KW") // ECDH-ES + AES key wrap (128)
|
||||
ECDH_ES_A192KW = KeyAlgorithm("ECDH-ES+A192KW") // ECDH-ES + AES key wrap (192)
|
||||
ECDH_ES_A256KW = KeyAlgorithm("ECDH-ES+A256KW") // ECDH-ES + AES key wrap (256)
|
||||
A128GCMKW = KeyAlgorithm("A128GCMKW") // AES-GCM key wrap (128)
|
||||
A192GCMKW = KeyAlgorithm("A192GCMKW") // AES-GCM key wrap (192)
|
||||
A256GCMKW = KeyAlgorithm("A256GCMKW") // AES-GCM key wrap (256)
|
||||
PBES2_HS256_A128KW = KeyAlgorithm("PBES2-HS256+A128KW") // PBES2 + HMAC-SHA256 + AES key wrap (128)
|
||||
PBES2_HS384_A192KW = KeyAlgorithm("PBES2-HS384+A192KW") // PBES2 + HMAC-SHA384 + AES key wrap (192)
|
||||
PBES2_HS512_A256KW = KeyAlgorithm("PBES2-HS512+A256KW") // PBES2 + HMAC-SHA512 + AES key wrap (256)
|
||||
)
|
||||
|
||||
// Signature algorithms
|
||||
const (
|
||||
EdDSA = SignatureAlgorithm("EdDSA")
|
||||
HS256 = SignatureAlgorithm("HS256") // HMAC using SHA-256
|
||||
HS384 = SignatureAlgorithm("HS384") // HMAC using SHA-384
|
||||
HS512 = SignatureAlgorithm("HS512") // HMAC using SHA-512
|
||||
RS256 = SignatureAlgorithm("RS256") // RSASSA-PKCS-v1.5 using SHA-256
|
||||
RS384 = SignatureAlgorithm("RS384") // RSASSA-PKCS-v1.5 using SHA-384
|
||||
RS512 = SignatureAlgorithm("RS512") // RSASSA-PKCS-v1.5 using SHA-512
|
||||
ES256 = SignatureAlgorithm("ES256") // ECDSA using P-256 and SHA-256
|
||||
ES384 = SignatureAlgorithm("ES384") // ECDSA using P-384 and SHA-384
|
||||
ES512 = SignatureAlgorithm("ES512") // ECDSA using P-521 and SHA-512
|
||||
PS256 = SignatureAlgorithm("PS256") // RSASSA-PSS using SHA256 and MGF1-SHA256
|
||||
PS384 = SignatureAlgorithm("PS384") // RSASSA-PSS using SHA384 and MGF1-SHA384
|
||||
PS512 = SignatureAlgorithm("PS512") // RSASSA-PSS using SHA512 and MGF1-SHA512
|
||||
)
|
||||
|
||||
// Content encryption algorithms
|
||||
const (
|
||||
A128CBC_HS256 = ContentEncryption("A128CBC-HS256") // AES-CBC + HMAC-SHA256 (128)
|
||||
A192CBC_HS384 = ContentEncryption("A192CBC-HS384") // AES-CBC + HMAC-SHA384 (192)
|
||||
A256CBC_HS512 = ContentEncryption("A256CBC-HS512") // AES-CBC + HMAC-SHA512 (256)
|
||||
A128GCM = ContentEncryption("A128GCM") // AES-GCM (128)
|
||||
A192GCM = ContentEncryption("A192GCM") // AES-GCM (192)
|
||||
A256GCM = ContentEncryption("A256GCM") // AES-GCM (256)
|
||||
)
|
||||
|
||||
// Compression algorithms
|
||||
const (
|
||||
NONE = CompressionAlgorithm("") // No compression
|
||||
DEFLATE = CompressionAlgorithm("DEF") // DEFLATE (RFC 1951)
|
||||
)
|
||||
|
||||
// A key in the protected header of a JWS object. Use of the Header...
|
||||
// constants is preferred to enhance type safety.
|
||||
type HeaderKey string
|
||||
|
||||
const (
|
||||
HeaderType = "typ" // string
|
||||
HeaderContentType = "cty" // string
|
||||
|
||||
// These are set by go-jose and shouldn't need to be set by consumers of the
|
||||
// library.
|
||||
headerAlgorithm = "alg" // string
|
||||
headerEncryption = "enc" // ContentEncryption
|
||||
headerCompression = "zip" // CompressionAlgorithm
|
||||
headerCritical = "crit" // []string
|
||||
|
||||
headerAPU = "apu" // *byteBuffer
|
||||
headerAPV = "apv" // *byteBuffer
|
||||
headerEPK = "epk" // *JSONWebKey
|
||||
headerIV = "iv" // *byteBuffer
|
||||
headerTag = "tag" // *byteBuffer
|
||||
headerX5c = "x5c" // []*x509.Certificate
|
||||
|
||||
headerJWK = "jwk" // *JSONWebKey
|
||||
headerKeyID = "kid" // string
|
||||
headerNonce = "nonce" // string
|
||||
headerB64 = "b64" // bool
|
||||
|
||||
headerP2C = "p2c" // *byteBuffer (int)
|
||||
headerP2S = "p2s" // *byteBuffer ([]byte)
|
||||
|
||||
)
|
||||
|
||||
// supportedCritical is the set of supported extensions that are understood and processed.
|
||||
var supportedCritical = map[string]bool{
|
||||
headerB64: true,
|
||||
}
|
||||
|
||||
// rawHeader represents the JOSE header for JWE/JWS objects (used for parsing).
|
||||
//
|
||||
// The decoding of the constituent items is deferred because we want to marshal
|
||||
// some members into particular structs rather than generic maps, but at the
|
||||
// same time we need to receive any extra fields unhandled by this library to
|
||||
// pass through to consuming code in case it wants to examine them.
|
||||
type rawHeader map[HeaderKey]*json.RawMessage
|
||||
|
||||
// Header represents the read-only JOSE header for JWE/JWS objects.
|
||||
type Header struct {
|
||||
KeyID string
|
||||
JSONWebKey *JSONWebKey
|
||||
Algorithm string
|
||||
Nonce string
|
||||
|
||||
// Unverified certificate chain parsed from x5c header.
|
||||
certificates []*x509.Certificate
|
||||
|
||||
// At parse time, each header parameter with a name other than "kid",
|
||||
// "jwk", "alg", "nonce", or "x5c" will have its value passed to
|
||||
// [json.Unmarshal] to unmarshal it into an interface value.
|
||||
// The resulting value will be stored in this map, with the header
|
||||
// parameter name as the key.
|
||||
//
|
||||
// [json.Unmarshal]: https://pkg.go.dev/encoding/json#Unmarshal
|
||||
ExtraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
// Certificates verifies & returns the certificate chain present
|
||||
// in the x5c header field of a message, if one was present. Returns
|
||||
// an error if there was no x5c header present or the chain could
|
||||
// not be validated with the given verify options.
|
||||
func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) {
|
||||
if len(h.certificates) == 0 {
|
||||
return nil, errors.New("go-jose/go-jose: no x5c header present in message")
|
||||
}
|
||||
|
||||
leaf := h.certificates[0]
|
||||
if opts.Intermediates == nil {
|
||||
opts.Intermediates = x509.NewCertPool()
|
||||
for _, intermediate := range h.certificates[1:] {
|
||||
opts.Intermediates.AddCert(intermediate)
|
||||
}
|
||||
}
|
||||
|
||||
return leaf.Verify(opts)
|
||||
}
|
||||
|
||||
func (parsed rawHeader) set(k HeaderKey, v interface{}) error {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parsed[k] = makeRawMessage(b)
|
||||
return nil
|
||||
}
|
||||
|
||||
// getString gets a string from the raw JSON, defaulting to "".
|
||||
func (parsed rawHeader) getString(k HeaderKey) string {
|
||||
v, ok := parsed[k]
|
||||
if !ok || v == nil {
|
||||
return ""
|
||||
}
|
||||
var s string
|
||||
err := json.Unmarshal(*v, &s)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// getByteBuffer gets a byte buffer from the raw JSON. Returns (nil, nil) if
|
||||
// not specified.
|
||||
func (parsed rawHeader) getByteBuffer(k HeaderKey) (*byteBuffer, error) {
|
||||
v := parsed[k]
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
var bb *byteBuffer
|
||||
err := json.Unmarshal(*v, &bb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bb, nil
|
||||
}
|
||||
|
||||
// getAlgorithm extracts parsed "alg" from the raw JSON as a KeyAlgorithm.
|
||||
func (parsed rawHeader) getAlgorithm() KeyAlgorithm {
|
||||
return KeyAlgorithm(parsed.getString(headerAlgorithm))
|
||||
}
|
||||
|
||||
// getSignatureAlgorithm extracts parsed "alg" from the raw JSON as a SignatureAlgorithm.
|
||||
func (parsed rawHeader) getSignatureAlgorithm() SignatureAlgorithm {
|
||||
return SignatureAlgorithm(parsed.getString(headerAlgorithm))
|
||||
}
|
||||
|
||||
// getEncryption extracts parsed "enc" from the raw JSON.
|
||||
func (parsed rawHeader) getEncryption() ContentEncryption {
|
||||
return ContentEncryption(parsed.getString(headerEncryption))
|
||||
}
|
||||
|
||||
// getCompression extracts parsed "zip" from the raw JSON.
|
||||
func (parsed rawHeader) getCompression() CompressionAlgorithm {
|
||||
return CompressionAlgorithm(parsed.getString(headerCompression))
|
||||
}
|
||||
|
||||
func (parsed rawHeader) getNonce() string {
|
||||
return parsed.getString(headerNonce)
|
||||
}
|
||||
|
||||
// getEPK extracts parsed "epk" from the raw JSON.
|
||||
func (parsed rawHeader) getEPK() (*JSONWebKey, error) {
|
||||
v := parsed[headerEPK]
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
var epk *JSONWebKey
|
||||
err := json.Unmarshal(*v, &epk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return epk, nil
|
||||
}
|
||||
|
||||
// getAPU extracts parsed "apu" from the raw JSON.
|
||||
func (parsed rawHeader) getAPU() (*byteBuffer, error) {
|
||||
return parsed.getByteBuffer(headerAPU)
|
||||
}
|
||||
|
||||
// getAPV extracts parsed "apv" from the raw JSON.
|
||||
func (parsed rawHeader) getAPV() (*byteBuffer, error) {
|
||||
return parsed.getByteBuffer(headerAPV)
|
||||
}
|
||||
|
||||
// getIV extracts parsed "iv" from the raw JSON.
|
||||
func (parsed rawHeader) getIV() (*byteBuffer, error) {
|
||||
return parsed.getByteBuffer(headerIV)
|
||||
}
|
||||
|
||||
// getTag extracts parsed "tag" from the raw JSON.
|
||||
func (parsed rawHeader) getTag() (*byteBuffer, error) {
|
||||
return parsed.getByteBuffer(headerTag)
|
||||
}
|
||||
|
||||
// getJWK extracts parsed "jwk" from the raw JSON.
|
||||
func (parsed rawHeader) getJWK() (*JSONWebKey, error) {
|
||||
v := parsed[headerJWK]
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
var jwk *JSONWebKey
|
||||
err := json.Unmarshal(*v, &jwk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jwk, nil
|
||||
}
|
||||
|
||||
// getCritical extracts parsed "crit" from the raw JSON. If omitted, it
|
||||
// returns an empty slice.
|
||||
func (parsed rawHeader) getCritical() ([]string, error) {
|
||||
v := parsed[headerCritical]
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var q []string
|
||||
err := json.Unmarshal(*v, &q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
// getS2C extracts parsed "p2c" from the raw JSON.
|
||||
func (parsed rawHeader) getP2C() (int, error) {
|
||||
v := parsed[headerP2C]
|
||||
if v == nil {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var p2c int
|
||||
err := json.Unmarshal(*v, &p2c)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return p2c, nil
|
||||
}
|
||||
|
||||
// getS2S extracts parsed "p2s" from the raw JSON.
|
||||
func (parsed rawHeader) getP2S() (*byteBuffer, error) {
|
||||
return parsed.getByteBuffer(headerP2S)
|
||||
}
|
||||
|
||||
// getB64 extracts parsed "b64" from the raw JSON, defaulting to true.
|
||||
func (parsed rawHeader) getB64() (bool, error) {
|
||||
v := parsed[headerB64]
|
||||
if v == nil {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
var b64 bool
|
||||
err := json.Unmarshal(*v, &b64)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return b64, nil
|
||||
}
|
||||
|
||||
// sanitized produces a cleaned-up header object from the raw JSON.
|
||||
func (parsed rawHeader) sanitized() (h Header, err error) {
|
||||
for k, v := range parsed {
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
switch k {
|
||||
case headerJWK:
|
||||
var jwk *JSONWebKey
|
||||
err = json.Unmarshal(*v, &jwk)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to unmarshal JWK: %v: %#v", err, string(*v))
|
||||
return
|
||||
}
|
||||
h.JSONWebKey = jwk
|
||||
case headerKeyID:
|
||||
var s string
|
||||
err = json.Unmarshal(*v, &s)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to unmarshal key ID: %v: %#v", err, string(*v))
|
||||
return
|
||||
}
|
||||
h.KeyID = s
|
||||
case headerAlgorithm:
|
||||
var s string
|
||||
err = json.Unmarshal(*v, &s)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to unmarshal algorithm: %v: %#v", err, string(*v))
|
||||
return
|
||||
}
|
||||
h.Algorithm = s
|
||||
case headerNonce:
|
||||
var s string
|
||||
err = json.Unmarshal(*v, &s)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to unmarshal nonce: %v: %#v", err, string(*v))
|
||||
return
|
||||
}
|
||||
h.Nonce = s
|
||||
case headerX5c:
|
||||
c := []string{}
|
||||
err = json.Unmarshal(*v, &c)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to unmarshal x5c header: %v: %#v", err, string(*v))
|
||||
return
|
||||
}
|
||||
h.certificates, err = parseCertificateChain(c)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to unmarshal x5c header: %v: %#v", err, string(*v))
|
||||
return
|
||||
}
|
||||
default:
|
||||
if h.ExtraHeaders == nil {
|
||||
h.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||
}
|
||||
var v2 interface{}
|
||||
err = json.Unmarshal(*v, &v2)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to unmarshal value: %v: %#v", err, string(*v))
|
||||
return
|
||||
}
|
||||
h.ExtraHeaders[k] = v2
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseCertificateChain(chain []string) ([]*x509.Certificate, error) {
|
||||
out := make([]*x509.Certificate, len(chain))
|
||||
for i, cert := range chain {
|
||||
raw, err := base64.StdEncoding.DecodeString(cert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[i], err = x509.ParseCertificate(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (parsed rawHeader) isSet(k HeaderKey) bool {
|
||||
dvr := parsed[k]
|
||||
if dvr == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var dv interface{}
|
||||
err := json.Unmarshal(*dvr, &dv)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if dvStr, ok := dv.(string); ok {
|
||||
return dvStr != ""
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Merge headers from src into dst, giving precedence to headers from l.
|
||||
func (parsed rawHeader) merge(src *rawHeader) {
|
||||
if src == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for k, v := range *src {
|
||||
if parsed.isSet(k) {
|
||||
continue
|
||||
}
|
||||
|
||||
parsed[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Get JOSE name of curve
|
||||
func curveName(crv elliptic.Curve) (string, error) {
|
||||
switch crv {
|
||||
case elliptic.P256():
|
||||
return "P-256", nil
|
||||
case elliptic.P384():
|
||||
return "P-384", nil
|
||||
case elliptic.P521():
|
||||
return "P-521", nil
|
||||
default:
|
||||
return "", fmt.Errorf("go-jose/go-jose: unsupported/unknown elliptic curve")
|
||||
}
|
||||
}
|
||||
|
||||
// Get size of curve in bytes
|
||||
func curveSize(crv elliptic.Curve) int {
|
||||
bits := crv.Params().BitSize
|
||||
|
||||
div := bits / 8
|
||||
mod := bits % 8
|
||||
|
||||
if mod == 0 {
|
||||
return div
|
||||
}
|
||||
|
||||
return div + 1
|
||||
}
|
||||
|
||||
func makeRawMessage(b []byte) *json.RawMessage {
|
||||
rm := json.RawMessage(b)
|
||||
return &rm
|
||||
}
|
487
vendor/github.com/go-jose/go-jose/v3/signing.go
generated
vendored
Normal file
487
vendor/github.com/go-jose/go-jose/v3/signing.go
generated
vendored
Normal file
@ -0,0 +1,487 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/rsa"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-jose/go-jose/v3/json"
|
||||
)
|
||||
|
||||
// NonceSource represents a source of random nonces to go into JWS objects
|
||||
type NonceSource interface {
|
||||
Nonce() (string, error)
|
||||
}
|
||||
|
||||
// Signer represents a signer which takes a payload and produces a signed JWS object.
|
||||
type Signer interface {
|
||||
Sign(payload []byte) (*JSONWebSignature, error)
|
||||
Options() SignerOptions
|
||||
}
|
||||
|
||||
// SigningKey represents an algorithm/key used to sign a message.
|
||||
//
|
||||
// Key must have one of these types:
|
||||
// - ed25519.PrivateKey
|
||||
// - *ecdsa.PrivateKey
|
||||
// - *rsa.PrivateKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - []byte (an HMAC key)
|
||||
// - Any type that satisfies the OpaqueSigner interface
|
||||
type SigningKey struct {
|
||||
Algorithm SignatureAlgorithm
|
||||
Key interface{}
|
||||
}
|
||||
|
||||
// SignerOptions represents options that can be set when creating signers.
|
||||
type SignerOptions struct {
|
||||
NonceSource NonceSource
|
||||
EmbedJWK bool
|
||||
|
||||
// Optional map of additional keys to be inserted into the protected header
|
||||
// of a JWS object. Some specifications which make use of JWS like to insert
|
||||
// additional values here.
|
||||
//
|
||||
// Values will be serialized by [json.Marshal] and must be valid inputs to
|
||||
// that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
ExtraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
// WithHeader adds an arbitrary value to the ExtraHeaders map, initializing it
|
||||
// if necessary, and returns the updated SignerOptions.
|
||||
//
|
||||
// The v argument will be serialized by [json.Marshal] and must be a valid
|
||||
// input to that function.
|
||||
//
|
||||
// [json.Marshal]: https://pkg.go.dev/encoding/json#Marshal
|
||||
func (so *SignerOptions) WithHeader(k HeaderKey, v interface{}) *SignerOptions {
|
||||
if so.ExtraHeaders == nil {
|
||||
so.ExtraHeaders = map[HeaderKey]interface{}{}
|
||||
}
|
||||
so.ExtraHeaders[k] = v
|
||||
return so
|
||||
}
|
||||
|
||||
// WithContentType adds a content type ("cty") header and returns the updated
|
||||
// SignerOptions.
|
||||
func (so *SignerOptions) WithContentType(contentType ContentType) *SignerOptions {
|
||||
return so.WithHeader(HeaderContentType, contentType)
|
||||
}
|
||||
|
||||
// WithType adds a type ("typ") header and returns the updated SignerOptions.
|
||||
func (so *SignerOptions) WithType(typ ContentType) *SignerOptions {
|
||||
return so.WithHeader(HeaderType, typ)
|
||||
}
|
||||
|
||||
// WithCritical adds the given names to the critical ("crit") header and returns
|
||||
// the updated SignerOptions.
|
||||
func (so *SignerOptions) WithCritical(names ...string) *SignerOptions {
|
||||
if so.ExtraHeaders[headerCritical] == nil {
|
||||
so.WithHeader(headerCritical, make([]string, 0, len(names)))
|
||||
}
|
||||
crit := so.ExtraHeaders[headerCritical].([]string)
|
||||
so.ExtraHeaders[headerCritical] = append(crit, names...)
|
||||
return so
|
||||
}
|
||||
|
||||
// WithBase64 adds a base64url-encode payload ("b64") header and returns the updated
|
||||
// SignerOptions. When the "b64" value is "false", the payload is not base64 encoded.
|
||||
func (so *SignerOptions) WithBase64(b64 bool) *SignerOptions {
|
||||
if !b64 {
|
||||
so.WithHeader(headerB64, b64)
|
||||
so.WithCritical(headerB64)
|
||||
}
|
||||
return so
|
||||
}
|
||||
|
||||
type payloadSigner interface {
|
||||
signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error)
|
||||
}
|
||||
|
||||
type payloadVerifier interface {
|
||||
verifyPayload(payload []byte, signature []byte, alg SignatureAlgorithm) error
|
||||
}
|
||||
|
||||
type genericSigner struct {
|
||||
recipients []recipientSigInfo
|
||||
nonceSource NonceSource
|
||||
embedJWK bool
|
||||
extraHeaders map[HeaderKey]interface{}
|
||||
}
|
||||
|
||||
type recipientSigInfo struct {
|
||||
sigAlg SignatureAlgorithm
|
||||
publicKey func() *JSONWebKey
|
||||
signer payloadSigner
|
||||
}
|
||||
|
||||
func staticPublicKey(jwk *JSONWebKey) func() *JSONWebKey {
|
||||
return func() *JSONWebKey {
|
||||
return jwk
|
||||
}
|
||||
}
|
||||
|
||||
// NewSigner creates an appropriate signer based on the key type
|
||||
func NewSigner(sig SigningKey, opts *SignerOptions) (Signer, error) {
|
||||
return NewMultiSigner([]SigningKey{sig}, opts)
|
||||
}
|
||||
|
||||
// NewMultiSigner creates a signer for multiple recipients
|
||||
func NewMultiSigner(sigs []SigningKey, opts *SignerOptions) (Signer, error) {
|
||||
signer := &genericSigner{recipients: []recipientSigInfo{}}
|
||||
|
||||
if opts != nil {
|
||||
signer.nonceSource = opts.NonceSource
|
||||
signer.embedJWK = opts.EmbedJWK
|
||||
signer.extraHeaders = opts.ExtraHeaders
|
||||
}
|
||||
|
||||
for _, sig := range sigs {
|
||||
err := signer.addRecipient(sig.Algorithm, sig.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return signer, nil
|
||||
}
|
||||
|
||||
// newVerifier creates a verifier based on the key type
|
||||
func newVerifier(verificationKey interface{}) (payloadVerifier, error) {
|
||||
switch verificationKey := verificationKey.(type) {
|
||||
case ed25519.PublicKey:
|
||||
return &edEncrypterVerifier{
|
||||
publicKey: verificationKey,
|
||||
}, nil
|
||||
case *rsa.PublicKey:
|
||||
return &rsaEncrypterVerifier{
|
||||
publicKey: verificationKey,
|
||||
}, nil
|
||||
case *ecdsa.PublicKey:
|
||||
return &ecEncrypterVerifier{
|
||||
publicKey: verificationKey,
|
||||
}, nil
|
||||
case []byte:
|
||||
return &symmetricMac{
|
||||
key: verificationKey,
|
||||
}, nil
|
||||
case JSONWebKey:
|
||||
return newVerifier(verificationKey.Key)
|
||||
case *JSONWebKey:
|
||||
return newVerifier(verificationKey.Key)
|
||||
case OpaqueVerifier:
|
||||
return &opaqueVerifier{verifier: verificationKey}, nil
|
||||
default:
|
||||
return nil, ErrUnsupportedKeyType
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *genericSigner) addRecipient(alg SignatureAlgorithm, signingKey interface{}) error {
|
||||
recipient, err := makeJWSRecipient(alg, signingKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx.recipients = append(ctx.recipients, recipient)
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeJWSRecipient(alg SignatureAlgorithm, signingKey interface{}) (recipientSigInfo, error) {
|
||||
switch signingKey := signingKey.(type) {
|
||||
case ed25519.PrivateKey:
|
||||
return newEd25519Signer(alg, signingKey)
|
||||
case *rsa.PrivateKey:
|
||||
return newRSASigner(alg, signingKey)
|
||||
case *ecdsa.PrivateKey:
|
||||
return newECDSASigner(alg, signingKey)
|
||||
case []byte:
|
||||
return newSymmetricSigner(alg, signingKey)
|
||||
case JSONWebKey:
|
||||
return newJWKSigner(alg, signingKey)
|
||||
case *JSONWebKey:
|
||||
return newJWKSigner(alg, *signingKey)
|
||||
case OpaqueSigner:
|
||||
return newOpaqueSigner(alg, signingKey)
|
||||
default:
|
||||
return recipientSigInfo{}, ErrUnsupportedKeyType
|
||||
}
|
||||
}
|
||||
|
||||
func newJWKSigner(alg SignatureAlgorithm, signingKey JSONWebKey) (recipientSigInfo, error) {
|
||||
recipient, err := makeJWSRecipient(alg, signingKey.Key)
|
||||
if err != nil {
|
||||
return recipientSigInfo{}, err
|
||||
}
|
||||
if recipient.publicKey != nil && recipient.publicKey() != nil {
|
||||
// recipient.publicKey is a JWK synthesized for embedding when recipientSigInfo
|
||||
// was created for the inner key (such as a RSA or ECDSA public key). It contains
|
||||
// the pub key for embedding, but doesn't have extra params like key id.
|
||||
publicKey := signingKey
|
||||
publicKey.Key = recipient.publicKey().Key
|
||||
recipient.publicKey = staticPublicKey(&publicKey)
|
||||
|
||||
// This should be impossible, but let's check anyway.
|
||||
if !recipient.publicKey().IsPublic() {
|
||||
return recipientSigInfo{}, errors.New("go-jose/go-jose: public key was unexpectedly not public")
|
||||
}
|
||||
}
|
||||
return recipient, nil
|
||||
}
|
||||
|
||||
func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
|
||||
obj := &JSONWebSignature{}
|
||||
obj.payload = payload
|
||||
obj.Signatures = make([]Signature, len(ctx.recipients))
|
||||
|
||||
for i, recipient := range ctx.recipients {
|
||||
protected := map[HeaderKey]interface{}{
|
||||
headerAlgorithm: string(recipient.sigAlg),
|
||||
}
|
||||
|
||||
if recipient.publicKey != nil && recipient.publicKey() != nil {
|
||||
// We want to embed the JWK or set the kid header, but not both. Having a protected
|
||||
// header that contains an embedded JWK while also simultaneously containing the kid
|
||||
// header is confusing, and at least in ACME the two are considered to be mutually
|
||||
// exclusive. The fact that both can exist at the same time is a somewhat unfortunate
|
||||
// result of the JOSE spec. We've decided that this library will only include one or
|
||||
// the other to avoid this confusion.
|
||||
//
|
||||
// See https://github.com/go-jose/go-jose/issues/157 for more context.
|
||||
if ctx.embedJWK {
|
||||
protected[headerJWK] = recipient.publicKey()
|
||||
} else {
|
||||
keyID := recipient.publicKey().KeyID
|
||||
if keyID != "" {
|
||||
protected[headerKeyID] = keyID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.nonceSource != nil {
|
||||
nonce, err := ctx.nonceSource.Nonce()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: Error generating nonce: %v", err)
|
||||
}
|
||||
protected[headerNonce] = nonce
|
||||
}
|
||||
|
||||
for k, v := range ctx.extraHeaders {
|
||||
protected[k] = v
|
||||
}
|
||||
|
||||
serializedProtected := mustSerializeJSON(protected)
|
||||
needsBase64 := true
|
||||
|
||||
if b64, ok := protected[headerB64]; ok {
|
||||
if needsBase64, ok = b64.(bool); !ok {
|
||||
return nil, errors.New("go-jose/go-jose: Invalid b64 header parameter")
|
||||
}
|
||||
}
|
||||
|
||||
var input bytes.Buffer
|
||||
|
||||
input.WriteString(base64.RawURLEncoding.EncodeToString(serializedProtected))
|
||||
input.WriteByte('.')
|
||||
|
||||
if needsBase64 {
|
||||
input.WriteString(base64.RawURLEncoding.EncodeToString(payload))
|
||||
} else {
|
||||
input.Write(payload)
|
||||
}
|
||||
|
||||
signatureInfo, err := recipient.signer.signPayload(input.Bytes(), recipient.sigAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
signatureInfo.protected = &rawHeader{}
|
||||
for k, v := range protected {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: Error marshalling item %#v: %v", k, err)
|
||||
}
|
||||
(*signatureInfo.protected)[k] = makeRawMessage(b)
|
||||
}
|
||||
obj.Signatures[i] = signatureInfo
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (ctx *genericSigner) Options() SignerOptions {
|
||||
return SignerOptions{
|
||||
NonceSource: ctx.nonceSource,
|
||||
EmbedJWK: ctx.embedJWK,
|
||||
ExtraHeaders: ctx.extraHeaders,
|
||||
}
|
||||
}
|
||||
|
||||
// Verify validates the signature on the object and returns the payload.
|
||||
// This function does not support multi-signature. If you desire multi-signature
|
||||
// verification use VerifyMulti instead.
|
||||
//
|
||||
// Be careful when verifying signatures based on embedded JWKs inside the
|
||||
// payload header. You cannot assume that the key received in a payload is
|
||||
// trusted.
|
||||
//
|
||||
// The verificationKey argument must have one of these types:
|
||||
// - ed25519.PublicKey
|
||||
// - *ecdsa.PublicKey
|
||||
// - *rsa.PublicKey
|
||||
// - *JSONWebKey
|
||||
// - JSONWebKey
|
||||
// - []byte (an HMAC key)
|
||||
// - Any type that implements the OpaqueVerifier interface.
|
||||
func (obj JSONWebSignature) Verify(verificationKey interface{}) ([]byte, error) {
|
||||
err := obj.DetachedVerify(obj.payload, verificationKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.payload, nil
|
||||
}
|
||||
|
||||
// UnsafePayloadWithoutVerification returns the payload without
|
||||
// verifying it. The content returned from this function cannot be
|
||||
// trusted.
|
||||
func (obj JSONWebSignature) UnsafePayloadWithoutVerification() []byte {
|
||||
return obj.payload
|
||||
}
|
||||
|
||||
// DetachedVerify validates a detached signature on the given payload. In
|
||||
// most cases, you will probably want to use Verify instead. DetachedVerify
|
||||
// is only useful if you have a payload and signature that are separated from
|
||||
// each other.
|
||||
//
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) DetachedVerify(payload []byte, verificationKey interface{}) error {
|
||||
key := tryJWKS(verificationKey, obj.headers()...)
|
||||
verifier, err := newVerifier(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(obj.Signatures) > 1 {
|
||||
return errors.New("go-jose/go-jose: too many signatures in payload; expecting only one")
|
||||
}
|
||||
|
||||
signature := obj.Signatures[0]
|
||||
headers := signature.mergedHeaders()
|
||||
critical, err := headers.getCritical()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, name := range critical {
|
||||
if !supportedCritical[name] {
|
||||
return ErrCryptoFailure
|
||||
}
|
||||
}
|
||||
|
||||
input, err := obj.computeAuthData(payload, &signature)
|
||||
if err != nil {
|
||||
return ErrCryptoFailure
|
||||
}
|
||||
|
||||
alg := headers.getSignatureAlgorithm()
|
||||
err = verifier.verifyPayload(input, signature.Signature, alg)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ErrCryptoFailure
|
||||
}
|
||||
|
||||
// VerifyMulti validates (one of the multiple) signatures on the object and
|
||||
// returns the index of the signature that was verified, along with the signature
|
||||
// object and the payload. We return the signature and index to guarantee that
|
||||
// callers are getting the verified value.
|
||||
//
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) VerifyMulti(verificationKey interface{}) (int, Signature, []byte, error) {
|
||||
idx, sig, err := obj.DetachedVerifyMulti(obj.payload, verificationKey)
|
||||
if err != nil {
|
||||
return -1, Signature{}, nil, err
|
||||
}
|
||||
return idx, sig, obj.payload, nil
|
||||
}
|
||||
|
||||
// DetachedVerifyMulti validates a detached signature on the given payload with
|
||||
// a signature/object that has potentially multiple signers. This returns the index
|
||||
// of the signature that was verified, along with the signature object. We return
|
||||
// the signature and index to guarantee that callers are getting the verified value.
|
||||
//
|
||||
// In most cases, you will probably want to use Verify or VerifyMulti instead.
|
||||
// DetachedVerifyMulti is only useful if you have a payload and signature that are
|
||||
// separated from each other, and the signature can have multiple signers at the
|
||||
// same time.
|
||||
//
|
||||
// The verificationKey argument must have one of the types allowed for the
|
||||
// verificationKey argument of JSONWebSignature.Verify().
|
||||
func (obj JSONWebSignature) DetachedVerifyMulti(payload []byte, verificationKey interface{}) (int, Signature, error) {
|
||||
key := tryJWKS(verificationKey, obj.headers()...)
|
||||
verifier, err := newVerifier(key)
|
||||
if err != nil {
|
||||
return -1, Signature{}, err
|
||||
}
|
||||
|
||||
outer:
|
||||
for i, signature := range obj.Signatures {
|
||||
headers := signature.mergedHeaders()
|
||||
critical, err := headers.getCritical()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, name := range critical {
|
||||
if !supportedCritical[name] {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
|
||||
input, err := obj.computeAuthData(payload, &signature)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
alg := headers.getSignatureAlgorithm()
|
||||
err = verifier.verifyPayload(input, signature.Signature, alg)
|
||||
if err == nil {
|
||||
return i, signature, nil
|
||||
}
|
||||
}
|
||||
|
||||
return -1, Signature{}, ErrCryptoFailure
|
||||
}
|
||||
|
||||
func (obj JSONWebSignature) headers() []Header {
|
||||
headers := make([]Header, len(obj.Signatures))
|
||||
for i, sig := range obj.Signatures {
|
||||
headers[i] = sig.Header
|
||||
}
|
||||
return headers
|
||||
}
|
505
vendor/github.com/go-jose/go-jose/v3/symmetric.go
generated
vendored
Normal file
505
vendor/github.com/go-jose/go-jose/v3/symmetric.go
generated
vendored
Normal file
@ -0,0 +1,505 @@
|
||||
/*-
|
||||
* Copyright 2014 Square Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jose
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
|
||||
josecipher "github.com/go-jose/go-jose/v3/cipher"
|
||||
)
|
||||
|
||||
// RandReader is a cryptographically secure random number generator (stubbed out in tests).
|
||||
var RandReader = rand.Reader
|
||||
|
||||
const (
|
||||
// RFC7518 recommends a minimum of 1,000 iterations:
|
||||
// - https://tools.ietf.org/html/rfc7518#section-4.8.1.2
|
||||
//
|
||||
// NIST recommends a minimum of 10,000:
|
||||
// - https://pages.nist.gov/800-63-3/sp800-63b.html
|
||||
//
|
||||
// 1Password increased in 2023 from 100,000 to 650,000:
|
||||
// - https://support.1password.com/pbkdf2/
|
||||
//
|
||||
// OWASP recommended 600,000 in Dec 2022:
|
||||
// - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
|
||||
defaultP2C = 600000
|
||||
// Default salt size: 128 bits
|
||||
defaultP2SSize = 16
|
||||
)
|
||||
|
||||
// Dummy key cipher for shared symmetric key mode
|
||||
type symmetricKeyCipher struct {
|
||||
key []byte // Pre-shared content-encryption key
|
||||
p2c int // PBES2 Count
|
||||
p2s []byte // PBES2 Salt Input
|
||||
}
|
||||
|
||||
// Signer/verifier for MAC modes
|
||||
type symmetricMac struct {
|
||||
key []byte
|
||||
}
|
||||
|
||||
// Input/output from an AEAD operation
|
||||
type aeadParts struct {
|
||||
iv, ciphertext, tag []byte
|
||||
}
|
||||
|
||||
// A content cipher based on an AEAD construction
|
||||
type aeadContentCipher struct {
|
||||
keyBytes int
|
||||
authtagBytes int
|
||||
getAead func(key []byte) (cipher.AEAD, error)
|
||||
}
|
||||
|
||||
// Random key generator
|
||||
type randomKeyGenerator struct {
|
||||
size int
|
||||
}
|
||||
|
||||
// Static key generator
|
||||
type staticKeyGenerator struct {
|
||||
key []byte
|
||||
}
|
||||
|
||||
// Create a new content cipher based on AES-GCM
|
||||
func newAESGCM(keySize int) contentCipher {
|
||||
return &aeadContentCipher{
|
||||
keyBytes: keySize,
|
||||
authtagBytes: 16,
|
||||
getAead: func(key []byte) (cipher.AEAD, error) {
|
||||
aes, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cipher.NewGCM(aes)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new content cipher based on AES-CBC+HMAC
|
||||
func newAESCBC(keySize int) contentCipher {
|
||||
return &aeadContentCipher{
|
||||
keyBytes: keySize * 2,
|
||||
authtagBytes: keySize,
|
||||
getAead: func(key []byte) (cipher.AEAD, error) {
|
||||
return josecipher.NewCBCHMAC(key, aes.NewCipher)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Get an AEAD cipher object for the given content encryption algorithm
|
||||
func getContentCipher(alg ContentEncryption) contentCipher {
|
||||
switch alg {
|
||||
case A128GCM:
|
||||
return newAESGCM(16)
|
||||
case A192GCM:
|
||||
return newAESGCM(24)
|
||||
case A256GCM:
|
||||
return newAESGCM(32)
|
||||
case A128CBC_HS256:
|
||||
return newAESCBC(16)
|
||||
case A192CBC_HS384:
|
||||
return newAESCBC(24)
|
||||
case A256CBC_HS512:
|
||||
return newAESCBC(32)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// getPbkdf2Params returns the key length and hash function used in
|
||||
// pbkdf2.Key.
|
||||
func getPbkdf2Params(alg KeyAlgorithm) (int, func() hash.Hash) {
|
||||
switch alg {
|
||||
case PBES2_HS256_A128KW:
|
||||
return 16, sha256.New
|
||||
case PBES2_HS384_A192KW:
|
||||
return 24, sha512.New384
|
||||
case PBES2_HS512_A256KW:
|
||||
return 32, sha512.New
|
||||
default:
|
||||
panic("invalid algorithm")
|
||||
}
|
||||
}
|
||||
|
||||
// getRandomSalt generates a new salt of the given size.
|
||||
func getRandomSalt(size int) ([]byte, error) {
|
||||
salt := make([]byte, size)
|
||||
_, err := io.ReadFull(RandReader, salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return salt, nil
|
||||
}
|
||||
|
||||
// newSymmetricRecipient creates a JWE encrypter based on AES-GCM key wrap.
|
||||
func newSymmetricRecipient(keyAlg KeyAlgorithm, key []byte) (recipientKeyInfo, error) {
|
||||
switch keyAlg {
|
||||
case DIRECT, A128GCMKW, A192GCMKW, A256GCMKW, A128KW, A192KW, A256KW:
|
||||
case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
|
||||
default:
|
||||
return recipientKeyInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
return recipientKeyInfo{
|
||||
keyAlg: keyAlg,
|
||||
keyEncrypter: &symmetricKeyCipher{
|
||||
key: key,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// newSymmetricSigner creates a recipientSigInfo based on the given key.
|
||||
func newSymmetricSigner(sigAlg SignatureAlgorithm, key []byte) (recipientSigInfo, error) {
|
||||
// Verify that key management algorithm is supported by this encrypter
|
||||
switch sigAlg {
|
||||
case HS256, HS384, HS512:
|
||||
default:
|
||||
return recipientSigInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
return recipientSigInfo{
|
||||
sigAlg: sigAlg,
|
||||
signer: &symmetricMac{
|
||||
key: key,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Generate a random key for the given content cipher
|
||||
func (ctx randomKeyGenerator) genKey() ([]byte, rawHeader, error) {
|
||||
key := make([]byte, ctx.size)
|
||||
_, err := io.ReadFull(RandReader, key)
|
||||
if err != nil {
|
||||
return nil, rawHeader{}, err
|
||||
}
|
||||
|
||||
return key, rawHeader{}, nil
|
||||
}
|
||||
|
||||
// Key size for random generator
|
||||
func (ctx randomKeyGenerator) keySize() int {
|
||||
return ctx.size
|
||||
}
|
||||
|
||||
// Generate a static key (for direct mode)
|
||||
func (ctx staticKeyGenerator) genKey() ([]byte, rawHeader, error) {
|
||||
cek := make([]byte, len(ctx.key))
|
||||
copy(cek, ctx.key)
|
||||
return cek, rawHeader{}, nil
|
||||
}
|
||||
|
||||
// Key size for static generator
|
||||
func (ctx staticKeyGenerator) keySize() int {
|
||||
return len(ctx.key)
|
||||
}
|
||||
|
||||
// Get key size for this cipher
|
||||
func (ctx aeadContentCipher) keySize() int {
|
||||
return ctx.keyBytes
|
||||
}
|
||||
|
||||
// Encrypt some data
|
||||
func (ctx aeadContentCipher) encrypt(key, aad, pt []byte) (*aeadParts, error) {
|
||||
// Get a new AEAD instance
|
||||
aead, err := ctx.getAead(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Initialize a new nonce
|
||||
iv := make([]byte, aead.NonceSize())
|
||||
_, err = io.ReadFull(RandReader, iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ciphertextAndTag := aead.Seal(nil, iv, pt, aad)
|
||||
offset := len(ciphertextAndTag) - ctx.authtagBytes
|
||||
|
||||
return &aeadParts{
|
||||
iv: iv,
|
||||
ciphertext: ciphertextAndTag[:offset],
|
||||
tag: ciphertextAndTag[offset:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Decrypt some data
|
||||
func (ctx aeadContentCipher) decrypt(key, aad []byte, parts *aeadParts) ([]byte, error) {
|
||||
aead, err := ctx.getAead(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(parts.iv) != aead.NonceSize() || len(parts.tag) < ctx.authtagBytes {
|
||||
return nil, ErrCryptoFailure
|
||||
}
|
||||
|
||||
return aead.Open(nil, parts.iv, append(parts.ciphertext, parts.tag...), aad)
|
||||
}
|
||||
|
||||
// Encrypt the content encryption key.
|
||||
func (ctx *symmetricKeyCipher) encryptKey(cek []byte, alg KeyAlgorithm) (recipientInfo, error) {
|
||||
switch alg {
|
||||
case DIRECT:
|
||||
return recipientInfo{
|
||||
header: &rawHeader{},
|
||||
}, nil
|
||||
case A128GCMKW, A192GCMKW, A256GCMKW:
|
||||
aead := newAESGCM(len(ctx.key))
|
||||
|
||||
parts, err := aead.encrypt(ctx.key, []byte{}, cek)
|
||||
if err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
header := &rawHeader{}
|
||||
|
||||
if err = header.set(headerIV, newBuffer(parts.iv)); err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
if err = header.set(headerTag, newBuffer(parts.tag)); err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
return recipientInfo{
|
||||
header: header,
|
||||
encryptedKey: parts.ciphertext,
|
||||
}, nil
|
||||
case A128KW, A192KW, A256KW:
|
||||
block, err := aes.NewCipher(ctx.key)
|
||||
if err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
jek, err := josecipher.KeyWrap(block, cek)
|
||||
if err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
return recipientInfo{
|
||||
encryptedKey: jek,
|
||||
header: &rawHeader{},
|
||||
}, nil
|
||||
case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
|
||||
if len(ctx.p2s) == 0 {
|
||||
salt, err := getRandomSalt(defaultP2SSize)
|
||||
if err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
ctx.p2s = salt
|
||||
}
|
||||
|
||||
if ctx.p2c <= 0 {
|
||||
ctx.p2c = defaultP2C
|
||||
}
|
||||
|
||||
// salt is UTF8(Alg) || 0x00 || Salt Input
|
||||
salt := bytes.Join([][]byte{[]byte(alg), ctx.p2s}, []byte{0x00})
|
||||
|
||||
// derive key
|
||||
keyLen, h := getPbkdf2Params(alg)
|
||||
key := pbkdf2.Key(ctx.key, salt, ctx.p2c, keyLen, h)
|
||||
|
||||
// use AES cipher with derived key
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
jek, err := josecipher.KeyWrap(block, cek)
|
||||
if err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
header := &rawHeader{}
|
||||
|
||||
if err = header.set(headerP2C, ctx.p2c); err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
if err = header.set(headerP2S, newBuffer(ctx.p2s)); err != nil {
|
||||
return recipientInfo{}, err
|
||||
}
|
||||
|
||||
return recipientInfo{
|
||||
encryptedKey: jek,
|
||||
header: header,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return recipientInfo{}, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
// Decrypt the content encryption key.
|
||||
func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipientInfo, generator keyGenerator) ([]byte, error) {
|
||||
switch headers.getAlgorithm() {
|
||||
case DIRECT:
|
||||
cek := make([]byte, len(ctx.key))
|
||||
copy(cek, ctx.key)
|
||||
return cek, nil
|
||||
case A128GCMKW, A192GCMKW, A256GCMKW:
|
||||
aead := newAESGCM(len(ctx.key))
|
||||
|
||||
iv, err := headers.getIV()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid IV: %v", err)
|
||||
}
|
||||
tag, err := headers.getTag()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid tag: %v", err)
|
||||
}
|
||||
|
||||
parts := &aeadParts{
|
||||
iv: iv.bytes(),
|
||||
ciphertext: recipient.encryptedKey,
|
||||
tag: tag.bytes(),
|
||||
}
|
||||
|
||||
cek, err := aead.decrypt(ctx.key, []byte{}, parts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cek, nil
|
||||
case A128KW, A192KW, A256KW:
|
||||
block, err := aes.NewCipher(ctx.key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cek, err := josecipher.KeyUnwrap(block, recipient.encryptedKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cek, nil
|
||||
case PBES2_HS256_A128KW, PBES2_HS384_A192KW, PBES2_HS512_A256KW:
|
||||
p2s, err := headers.getP2S()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: %v", err)
|
||||
}
|
||||
if p2s == nil || len(p2s.data) == 0 {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: must be present")
|
||||
}
|
||||
|
||||
p2c, err := headers.getP2C()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: %v", err)
|
||||
}
|
||||
if p2c <= 0 {
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: must be a positive integer")
|
||||
}
|
||||
if p2c > 1000000 {
|
||||
// An unauthenticated attacker can set a high P2C value. Set an upper limit to avoid
|
||||
// DoS attacks.
|
||||
return nil, fmt.Errorf("go-jose/go-jose: invalid P2C: too high")
|
||||
}
|
||||
|
||||
// salt is UTF8(Alg) || 0x00 || Salt Input
|
||||
alg := headers.getAlgorithm()
|
||||
salt := bytes.Join([][]byte{[]byte(alg), p2s.bytes()}, []byte{0x00})
|
||||
|
||||
// derive key
|
||||
keyLen, h := getPbkdf2Params(alg)
|
||||
key := pbkdf2.Key(ctx.key, salt, p2c, keyLen, h)
|
||||
|
||||
// use AES cipher with derived key
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cek, err := josecipher.KeyUnwrap(block, recipient.encryptedKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cek, nil
|
||||
}
|
||||
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
// Sign the given payload
|
||||
func (ctx symmetricMac) signPayload(payload []byte, alg SignatureAlgorithm) (Signature, error) {
|
||||
mac, err := ctx.hmac(payload, alg)
|
||||
if err != nil {
|
||||
return Signature{}, errors.New("go-jose/go-jose: failed to compute hmac")
|
||||
}
|
||||
|
||||
return Signature{
|
||||
Signature: mac,
|
||||
protected: &rawHeader{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Verify the given payload
|
||||
func (ctx symmetricMac) verifyPayload(payload []byte, mac []byte, alg SignatureAlgorithm) error {
|
||||
expected, err := ctx.hmac(payload, alg)
|
||||
if err != nil {
|
||||
return errors.New("go-jose/go-jose: failed to compute hmac")
|
||||
}
|
||||
|
||||
if len(mac) != len(expected) {
|
||||
return errors.New("go-jose/go-jose: invalid hmac")
|
||||
}
|
||||
|
||||
match := subtle.ConstantTimeCompare(mac, expected)
|
||||
if match != 1 {
|
||||
return errors.New("go-jose/go-jose: invalid hmac")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Compute the HMAC based on the given alg value
|
||||
func (ctx symmetricMac) hmac(payload []byte, alg SignatureAlgorithm) ([]byte, error) {
|
||||
var hash func() hash.Hash
|
||||
|
||||
switch alg {
|
||||
case HS256:
|
||||
hash = sha256.New
|
||||
case HS384:
|
||||
hash = sha512.New384
|
||||
case HS512:
|
||||
hash = sha512.New
|
||||
default:
|
||||
return nil, ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
hmac := hmac.New(hash, ctx.key)
|
||||
|
||||
// According to documentation, Write() on hash never fails
|
||||
_, _ = hmac.Write(payload)
|
||||
return hmac.Sum(nil), nil
|
||||
}
|
3
vendor/github.com/miekg/pkcs11/.gitignore
generated
vendored
Normal file
3
vendor/github.com/miekg/pkcs11/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
tags
|
||||
test_db/*/generation
|
||||
test_db/*/*.lock
|
27
vendor/github.com/miekg/pkcs11/LICENSE
generated
vendored
Normal file
27
vendor/github.com/miekg/pkcs11/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2013 Miek Gieben. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Miek Gieben nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
57
vendor/github.com/miekg/pkcs11/Makefile.release
generated
vendored
Normal file
57
vendor/github.com/miekg/pkcs11/Makefile.release
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
# Makefile for releasing.
|
||||
#
|
||||
# The release is controlled from version.go. The version found there is
|
||||
# used to tag the git repo, we're not building any artifects so there is nothing
|
||||
# to upload to github.
|
||||
#
|
||||
# * Up the version in version.go
|
||||
# * Run: make -f Makefile.release release
|
||||
# * will *commit* your change with 'Release $VERSION'
|
||||
# * push to github
|
||||
#
|
||||
|
||||
define GO
|
||||
//+build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/miekg/pkcs11"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(pkcs11.Release.String())
|
||||
}
|
||||
endef
|
||||
|
||||
$(file > version_release.go,$(GO))
|
||||
VERSION:=$(shell go run -tags release version_release.go)
|
||||
TAG="v$(VERSION)"
|
||||
|
||||
all:
|
||||
rm -f version_release.go
|
||||
@echo Use the \'release\' target to start a release $(VERSION)
|
||||
|
||||
.PHONY: run
|
||||
run:
|
||||
rm -f version_release.go
|
||||
@echo $(VERSION)
|
||||
|
||||
.PHONY: release
|
||||
release: commit push
|
||||
@echo Released $(VERSION)
|
||||
|
||||
.PHONY: commit
|
||||
commit:
|
||||
rm -f version_release.go
|
||||
@echo Committing release $(VERSION)
|
||||
git commit -am"Release $(VERSION)"
|
||||
git tag $(TAG)
|
||||
|
||||
.PHONY: push
|
||||
push:
|
||||
@echo Pushing release $(VERSION) to master
|
||||
git push --tags
|
||||
git push
|
68
vendor/github.com/miekg/pkcs11/README.md
generated
vendored
Normal file
68
vendor/github.com/miekg/pkcs11/README.md
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
# PKCS#11
|
||||
|
||||
This is a Go implementation of the PKCS#11 API. It wraps the library closely, but uses Go idiom where
|
||||
it makes sense. It has been tested with SoftHSM.
|
||||
|
||||
## SoftHSM
|
||||
|
||||
* Make it use a custom configuration file `export SOFTHSM_CONF=$PWD/softhsm.conf`
|
||||
|
||||
* Then use `softhsm` to init it
|
||||
|
||||
~~~
|
||||
softhsm --init-token --slot 0 --label test --pin 1234
|
||||
~~~
|
||||
|
||||
* Then use `libsofthsm2.so` as the pkcs11 module:
|
||||
|
||||
~~~ go
|
||||
p := pkcs11.New("/usr/lib/softhsm/libsofthsm2.so")
|
||||
~~~
|
||||
|
||||
## Examples
|
||||
|
||||
A skeleton program would look somewhat like this (yes, pkcs#11 is verbose):
|
||||
|
||||
~~~ go
|
||||
p := pkcs11.New("/usr/lib/softhsm/libsofthsm2.so")
|
||||
err := p.Initialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
defer p.Destroy()
|
||||
defer p.Finalize()
|
||||
|
||||
slots, err := p.GetSlotList(true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
session, err := p.OpenSession(slots[0], pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer p.CloseSession(session)
|
||||
|
||||
err = p.Login(session, pkcs11.CKU_USER, "1234")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer p.Logout(session)
|
||||
|
||||
p.DigestInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_SHA_1, nil)})
|
||||
hash, err := p.Digest(session, []byte("this is a string"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, d := range hash {
|
||||
fmt.Printf("%x", d)
|
||||
}
|
||||
fmt.Println()
|
||||
~~~
|
||||
|
||||
Further examples are included in the tests.
|
||||
|
||||
To expose PKCS#11 keys using the [crypto.Signer interface](https://golang.org/pkg/crypto/#Signer),
|
||||
please see [github.com/thalesignite/crypto11](https://github.com/thalesignite/crypto11).
|
98
vendor/github.com/miekg/pkcs11/error.go
generated
vendored
Normal file
98
vendor/github.com/miekg/pkcs11/error.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2013 Miek Gieben. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pkcs11
|
||||
|
||||
// awk '/#define CKR_/{ print $3":\""$2"\"," }' pkcs11t.h
|
||||
|
||||
var strerror = map[uint]string{
|
||||
0x00000000: "CKR_OK",
|
||||
0x00000001: "CKR_CANCEL",
|
||||
0x00000002: "CKR_HOST_MEMORY",
|
||||
0x00000003: "CKR_SLOT_ID_INVALID",
|
||||
0x00000005: "CKR_GENERAL_ERROR",
|
||||
0x00000006: "CKR_FUNCTION_FAILED",
|
||||
0x00000007: "CKR_ARGUMENTS_BAD",
|
||||
0x00000008: "CKR_NO_EVENT",
|
||||
0x00000009: "CKR_NEED_TO_CREATE_THREADS",
|
||||
0x0000000A: "CKR_CANT_LOCK",
|
||||
0x00000010: "CKR_ATTRIBUTE_READ_ONLY",
|
||||
0x00000011: "CKR_ATTRIBUTE_SENSITIVE",
|
||||
0x00000012: "CKR_ATTRIBUTE_TYPE_INVALID",
|
||||
0x00000013: "CKR_ATTRIBUTE_VALUE_INVALID",
|
||||
0x00000020: "CKR_DATA_INVALID",
|
||||
0x00000021: "CKR_DATA_LEN_RANGE",
|
||||
0x00000030: "CKR_DEVICE_ERROR",
|
||||
0x00000031: "CKR_DEVICE_MEMORY",
|
||||
0x00000032: "CKR_DEVICE_REMOVED",
|
||||
0x00000040: "CKR_ENCRYPTED_DATA_INVALID",
|
||||
0x00000041: "CKR_ENCRYPTED_DATA_LEN_RANGE",
|
||||
0x00000050: "CKR_FUNCTION_CANCELED",
|
||||
0x00000051: "CKR_FUNCTION_NOT_PARALLEL",
|
||||
0x00000054: "CKR_FUNCTION_NOT_SUPPORTED",
|
||||
0x00000060: "CKR_KEY_HANDLE_INVALID",
|
||||
0x00000062: "CKR_KEY_SIZE_RANGE",
|
||||
0x00000063: "CKR_KEY_TYPE_INCONSISTENT",
|
||||
0x00000064: "CKR_KEY_NOT_NEEDED",
|
||||
0x00000065: "CKR_KEY_CHANGED",
|
||||
0x00000066: "CKR_KEY_NEEDED",
|
||||
0x00000067: "CKR_KEY_INDIGESTIBLE",
|
||||
0x00000068: "CKR_KEY_FUNCTION_NOT_PERMITTED",
|
||||
0x00000069: "CKR_KEY_NOT_WRAPPABLE",
|
||||
0x0000006A: "CKR_KEY_UNEXTRACTABLE",
|
||||
0x00000070: "CKR_MECHANISM_INVALID",
|
||||
0x00000071: "CKR_MECHANISM_PARAM_INVALID",
|
||||
0x00000082: "CKR_OBJECT_HANDLE_INVALID",
|
||||
0x00000090: "CKR_OPERATION_ACTIVE",
|
||||
0x00000091: "CKR_OPERATION_NOT_INITIALIZED",
|
||||
0x000000A0: "CKR_PIN_INCORRECT",
|
||||
0x000000A1: "CKR_PIN_INVALID",
|
||||
0x000000A2: "CKR_PIN_LEN_RANGE",
|
||||
0x000000A3: "CKR_PIN_EXPIRED",
|
||||
0x000000A4: "CKR_PIN_LOCKED",
|
||||
0x000000B0: "CKR_SESSION_CLOSED",
|
||||
0x000000B1: "CKR_SESSION_COUNT",
|
||||
0x000000B3: "CKR_SESSION_HANDLE_INVALID",
|
||||
0x000000B4: "CKR_SESSION_PARALLEL_NOT_SUPPORTED",
|
||||
0x000000B5: "CKR_SESSION_READ_ONLY",
|
||||
0x000000B6: "CKR_SESSION_EXISTS",
|
||||
0x000000B7: "CKR_SESSION_READ_ONLY_EXISTS",
|
||||
0x000000B8: "CKR_SESSION_READ_WRITE_SO_EXISTS",
|
||||
0x000000C0: "CKR_SIGNATURE_INVALID",
|
||||
0x000000C1: "CKR_SIGNATURE_LEN_RANGE",
|
||||
0x000000D0: "CKR_TEMPLATE_INCOMPLETE",
|
||||
0x000000D1: "CKR_TEMPLATE_INCONSISTENT",
|
||||
0x000000E0: "CKR_TOKEN_NOT_PRESENT",
|
||||
0x000000E1: "CKR_TOKEN_NOT_RECOGNIZED",
|
||||
0x000000E2: "CKR_TOKEN_WRITE_PROTECTED",
|
||||
0x000000F0: "CKR_UNWRAPPING_KEY_HANDLE_INVALID",
|
||||
0x000000F1: "CKR_UNWRAPPING_KEY_SIZE_RANGE",
|
||||
0x000000F2: "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT",
|
||||
0x00000100: "CKR_USER_ALREADY_LOGGED_IN",
|
||||
0x00000101: "CKR_USER_NOT_LOGGED_IN",
|
||||
0x00000102: "CKR_USER_PIN_NOT_INITIALIZED",
|
||||
0x00000103: "CKR_USER_TYPE_INVALID",
|
||||
0x00000104: "CKR_USER_ANOTHER_ALREADY_LOGGED_IN",
|
||||
0x00000105: "CKR_USER_TOO_MANY_TYPES",
|
||||
0x00000110: "CKR_WRAPPED_KEY_INVALID",
|
||||
0x00000112: "CKR_WRAPPED_KEY_LEN_RANGE",
|
||||
0x00000113: "CKR_WRAPPING_KEY_HANDLE_INVALID",
|
||||
0x00000114: "CKR_WRAPPING_KEY_SIZE_RANGE",
|
||||
0x00000115: "CKR_WRAPPING_KEY_TYPE_INCONSISTENT",
|
||||
0x00000120: "CKR_RANDOM_SEED_NOT_SUPPORTED",
|
||||
0x00000121: "CKR_RANDOM_NO_RNG",
|
||||
0x00000130: "CKR_DOMAIN_PARAMS_INVALID",
|
||||
0x00000150: "CKR_BUFFER_TOO_SMALL",
|
||||
0x00000160: "CKR_SAVED_STATE_INVALID",
|
||||
0x00000170: "CKR_INFORMATION_SENSITIVE",
|
||||
0x00000180: "CKR_STATE_UNSAVEABLE",
|
||||
0x00000190: "CKR_CRYPTOKI_NOT_INITIALIZED",
|
||||
0x00000191: "CKR_CRYPTOKI_ALREADY_INITIALIZED",
|
||||
0x000001A0: "CKR_MUTEX_BAD",
|
||||
0x000001A1: "CKR_MUTEX_NOT_LOCKED",
|
||||
0x000001B0: "CKR_NEW_PIN_MODE",
|
||||
0x000001B1: "CKR_NEXT_OTP",
|
||||
0x00000200: "CKR_FUNCTION_REJECTED",
|
||||
0x80000000: "CKR_VENDOR_DEFINED",
|
||||
}
|
BIN
vendor/github.com/miekg/pkcs11/hsm.db
generated
vendored
Normal file
BIN
vendor/github.com/miekg/pkcs11/hsm.db
generated
vendored
Normal file
Binary file not shown.
190
vendor/github.com/miekg/pkcs11/params.go
generated
vendored
Normal file
190
vendor/github.com/miekg/pkcs11/params.go
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
// Copyright 2013 Miek Gieben. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pkcs11
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pkcs11go.h"
|
||||
|
||||
static inline void putOAEPParams(CK_RSA_PKCS_OAEP_PARAMS_PTR params, CK_VOID_PTR pSourceData, CK_ULONG ulSourceDataLen)
|
||||
{
|
||||
params->pSourceData = pSourceData;
|
||||
params->ulSourceDataLen = ulSourceDataLen;
|
||||
}
|
||||
|
||||
static inline void putECDH1SharedParams(CK_ECDH1_DERIVE_PARAMS_PTR params, CK_VOID_PTR pSharedData, CK_ULONG ulSharedDataLen)
|
||||
{
|
||||
params->pSharedData = pSharedData;
|
||||
params->ulSharedDataLen = ulSharedDataLen;
|
||||
}
|
||||
|
||||
static inline void putECDH1PublicParams(CK_ECDH1_DERIVE_PARAMS_PTR params, CK_VOID_PTR pPublicData, CK_ULONG ulPublicDataLen)
|
||||
{
|
||||
params->pPublicData = pPublicData;
|
||||
params->ulPublicDataLen = ulPublicDataLen;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
// GCMParams represents the parameters for the AES-GCM mechanism.
|
||||
type GCMParams struct {
|
||||
arena
|
||||
params *C.CK_GCM_PARAMS
|
||||
iv []byte
|
||||
aad []byte
|
||||
tagSize int
|
||||
}
|
||||
|
||||
// NewGCMParams returns a pointer to AES-GCM parameters that can be used with the CKM_AES_GCM mechanism.
|
||||
// The Free() method must be called after the operation is complete.
|
||||
//
|
||||
// Note that some HSMs, like CloudHSM, will ignore the IV you pass in and write their
|
||||
// own. As a result, to support all libraries, memory is not freed
|
||||
// automatically, so that after the EncryptInit/Encrypt operation the HSM's IV
|
||||
// can be read back out. It is up to the caller to ensure that Free() is called
|
||||
// on the GCMParams object at an appropriate time, which is after
|
||||
//
|
||||
// Encrypt/Decrypt. As an example:
|
||||
//
|
||||
// gcmParams := pkcs11.NewGCMParams(make([]byte, 12), nil, 128)
|
||||
// p.ctx.EncryptInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_GCM, gcmParams)},
|
||||
// aesObjHandle)
|
||||
// ct, _ := p.ctx.Encrypt(session, pt)
|
||||
// iv := gcmParams.IV()
|
||||
// gcmParams.Free()
|
||||
//
|
||||
func NewGCMParams(iv, aad []byte, tagSize int) *GCMParams {
|
||||
return &GCMParams{
|
||||
iv: iv,
|
||||
aad: aad,
|
||||
tagSize: tagSize,
|
||||
}
|
||||
}
|
||||
|
||||
func cGCMParams(p *GCMParams) []byte {
|
||||
params := C.CK_GCM_PARAMS{
|
||||
ulTagBits: C.CK_ULONG(p.tagSize),
|
||||
}
|
||||
var arena arena
|
||||
if len(p.iv) > 0 {
|
||||
iv, ivLen := arena.Allocate(p.iv)
|
||||
params.pIv = C.CK_BYTE_PTR(iv)
|
||||
params.ulIvLen = ivLen
|
||||
params.ulIvBits = ivLen * 8
|
||||
}
|
||||
if len(p.aad) > 0 {
|
||||
aad, aadLen := arena.Allocate(p.aad)
|
||||
params.pAAD = C.CK_BYTE_PTR(aad)
|
||||
params.ulAADLen = aadLen
|
||||
}
|
||||
p.Free()
|
||||
p.arena = arena
|
||||
p.params = ¶ms
|
||||
return C.GoBytes(unsafe.Pointer(¶ms), C.int(unsafe.Sizeof(params)))
|
||||
}
|
||||
|
||||
// IV returns a copy of the actual IV used for the operation.
|
||||
//
|
||||
// Some HSMs may ignore the user-specified IV and write their own at the end of
|
||||
// the encryption operation; this method allows you to retrieve it.
|
||||
func (p *GCMParams) IV() []byte {
|
||||
if p == nil || p.params == nil {
|
||||
return nil
|
||||
}
|
||||
newIv := C.GoBytes(unsafe.Pointer(p.params.pIv), C.int(p.params.ulIvLen))
|
||||
iv := make([]byte, len(newIv))
|
||||
copy(iv, newIv)
|
||||
return iv
|
||||
}
|
||||
|
||||
// Free deallocates the memory reserved for the HSM to write back the actual IV.
|
||||
//
|
||||
// This must be called after the entire operation is complete, i.e. after
|
||||
// Encrypt or EncryptFinal. It is safe to call Free multiple times.
|
||||
func (p *GCMParams) Free() {
|
||||
if p == nil || p.arena == nil {
|
||||
return
|
||||
}
|
||||
p.arena.Free()
|
||||
p.params = nil
|
||||
p.arena = nil
|
||||
}
|
||||
|
||||
// NewPSSParams creates a CK_RSA_PKCS_PSS_PARAMS structure and returns it as a byte array for use with the CKM_RSA_PKCS_PSS mechanism.
|
||||
func NewPSSParams(hashAlg, mgf, saltLength uint) []byte {
|
||||
p := C.CK_RSA_PKCS_PSS_PARAMS{
|
||||
hashAlg: C.CK_MECHANISM_TYPE(hashAlg),
|
||||
mgf: C.CK_RSA_PKCS_MGF_TYPE(mgf),
|
||||
sLen: C.CK_ULONG(saltLength),
|
||||
}
|
||||
return C.GoBytes(unsafe.Pointer(&p), C.int(unsafe.Sizeof(p)))
|
||||
}
|
||||
|
||||
// OAEPParams can be passed to NewMechanism to implement CKM_RSA_PKCS_OAEP.
|
||||
type OAEPParams struct {
|
||||
HashAlg uint
|
||||
MGF uint
|
||||
SourceType uint
|
||||
SourceData []byte
|
||||
}
|
||||
|
||||
// NewOAEPParams creates a CK_RSA_PKCS_OAEP_PARAMS structure suitable for use with the CKM_RSA_PKCS_OAEP mechanism.
|
||||
func NewOAEPParams(hashAlg, mgf, sourceType uint, sourceData []byte) *OAEPParams {
|
||||
return &OAEPParams{
|
||||
HashAlg: hashAlg,
|
||||
MGF: mgf,
|
||||
SourceType: sourceType,
|
||||
SourceData: sourceData,
|
||||
}
|
||||
}
|
||||
|
||||
func cOAEPParams(p *OAEPParams, arena arena) ([]byte, arena) {
|
||||
params := C.CK_RSA_PKCS_OAEP_PARAMS{
|
||||
hashAlg: C.CK_MECHANISM_TYPE(p.HashAlg),
|
||||
mgf: C.CK_RSA_PKCS_MGF_TYPE(p.MGF),
|
||||
source: C.CK_RSA_PKCS_OAEP_SOURCE_TYPE(p.SourceType),
|
||||
}
|
||||
if len(p.SourceData) != 0 {
|
||||
buf, len := arena.Allocate(p.SourceData)
|
||||
// field is unaligned on windows so this has to call into C
|
||||
C.putOAEPParams(¶ms, buf, len)
|
||||
}
|
||||
return C.GoBytes(unsafe.Pointer(¶ms), C.int(unsafe.Sizeof(params))), arena
|
||||
}
|
||||
|
||||
// ECDH1DeriveParams can be passed to NewMechanism to implement CK_ECDH1_DERIVE_PARAMS.
|
||||
type ECDH1DeriveParams struct {
|
||||
KDF uint
|
||||
SharedData []byte
|
||||
PublicKeyData []byte
|
||||
}
|
||||
|
||||
// NewECDH1DeriveParams creates a CK_ECDH1_DERIVE_PARAMS structure suitable for use with the CKM_ECDH1_DERIVE mechanism.
|
||||
func NewECDH1DeriveParams(kdf uint, sharedData []byte, publicKeyData []byte) *ECDH1DeriveParams {
|
||||
return &ECDH1DeriveParams{
|
||||
KDF: kdf,
|
||||
SharedData: sharedData,
|
||||
PublicKeyData: publicKeyData,
|
||||
}
|
||||
}
|
||||
|
||||
func cECDH1DeriveParams(p *ECDH1DeriveParams, arena arena) ([]byte, arena) {
|
||||
params := C.CK_ECDH1_DERIVE_PARAMS{
|
||||
kdf: C.CK_EC_KDF_TYPE(p.KDF),
|
||||
}
|
||||
|
||||
// SharedData MUST be null if key derivation function (KDF) is CKD_NULL
|
||||
if len(p.SharedData) != 0 {
|
||||
sharedData, sharedDataLen := arena.Allocate(p.SharedData)
|
||||
C.putECDH1SharedParams(¶ms, sharedData, sharedDataLen)
|
||||
}
|
||||
|
||||
publicKeyData, publicKeyDataLen := arena.Allocate(p.PublicKeyData)
|
||||
C.putECDH1PublicParams(¶ms, publicKeyData, publicKeyDataLen)
|
||||
|
||||
return C.GoBytes(unsafe.Pointer(¶ms), C.int(unsafe.Sizeof(params))), arena
|
||||
}
|
1609
vendor/github.com/miekg/pkcs11/pkcs11.go
generated
vendored
Normal file
1609
vendor/github.com/miekg/pkcs11/pkcs11.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
265
vendor/github.com/miekg/pkcs11/pkcs11.h
generated
vendored
Normal file
265
vendor/github.com/miekg/pkcs11/pkcs11.h
generated
vendored
Normal file
@ -0,0 +1,265 @@
|
||||
/* Copyright (c) OASIS Open 2016. All Rights Reserved./
|
||||
* /Distributed under the terms of the OASIS IPR Policy,
|
||||
* [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
|
||||
* IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
|
||||
*/
|
||||
|
||||
/* Latest version of the specification:
|
||||
* http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
|
||||
*/
|
||||
|
||||
#ifndef _PKCS11_H_
|
||||
#define _PKCS11_H_ 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Before including this file (pkcs11.h) (or pkcs11t.h by
|
||||
* itself), 5 platform-specific macros must be defined. These
|
||||
* macros are described below, and typical definitions for them
|
||||
* are also given. Be advised that these definitions can depend
|
||||
* on both the platform and the compiler used (and possibly also
|
||||
* on whether a Cryptoki library is linked statically or
|
||||
* dynamically).
|
||||
*
|
||||
* In addition to defining these 5 macros, the packing convention
|
||||
* for Cryptoki structures should be set. The Cryptoki
|
||||
* convention on packing is that structures should be 1-byte
|
||||
* aligned.
|
||||
*
|
||||
* If you're using Microsoft Developer Studio 5.0 to produce
|
||||
* Win32 stuff, this might be done by using the following
|
||||
* preprocessor directive before including pkcs11.h or pkcs11t.h:
|
||||
*
|
||||
* #pragma pack(push, cryptoki, 1)
|
||||
*
|
||||
* and using the following preprocessor directive after including
|
||||
* pkcs11.h or pkcs11t.h:
|
||||
*
|
||||
* #pragma pack(pop, cryptoki)
|
||||
*
|
||||
* If you're using an earlier version of Microsoft Developer
|
||||
* Studio to produce Win16 stuff, this might be done by using
|
||||
* the following preprocessor directive before including
|
||||
* pkcs11.h or pkcs11t.h:
|
||||
*
|
||||
* #pragma pack(1)
|
||||
*
|
||||
* In a UNIX environment, you're on your own for this. You might
|
||||
* not need to do (or be able to do!) anything.
|
||||
*
|
||||
*
|
||||
* Now for the macros:
|
||||
*
|
||||
*
|
||||
* 1. CK_PTR: The indirection string for making a pointer to an
|
||||
* object. It can be used like this:
|
||||
*
|
||||
* typedef CK_BYTE CK_PTR CK_BYTE_PTR;
|
||||
*
|
||||
* If you're using Microsoft Developer Studio 5.0 to produce
|
||||
* Win32 stuff, it might be defined by:
|
||||
*
|
||||
* #define CK_PTR *
|
||||
*
|
||||
* If you're using an earlier version of Microsoft Developer
|
||||
* Studio to produce Win16 stuff, it might be defined by:
|
||||
*
|
||||
* #define CK_PTR far *
|
||||
*
|
||||
* In a typical UNIX environment, it might be defined by:
|
||||
*
|
||||
* #define CK_PTR *
|
||||
*
|
||||
*
|
||||
* 2. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
|
||||
* an importable Cryptoki library function declaration out of a
|
||||
* return type and a function name. It should be used in the
|
||||
* following fashion:
|
||||
*
|
||||
* extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
|
||||
* CK_VOID_PTR pReserved
|
||||
* );
|
||||
*
|
||||
* If you're using Microsoft Developer Studio 5.0 to declare a
|
||||
* function in a Win32 Cryptoki .dll, it might be defined by:
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION(returnType, name) \
|
||||
* returnType __declspec(dllimport) name
|
||||
*
|
||||
* If you're using an earlier version of Microsoft Developer
|
||||
* Studio to declare a function in a Win16 Cryptoki .dll, it
|
||||
* might be defined by:
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION(returnType, name) \
|
||||
* returnType __export _far _pascal name
|
||||
*
|
||||
* In a UNIX environment, it might be defined by:
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION(returnType, name) \
|
||||
* returnType name
|
||||
*
|
||||
*
|
||||
* 3. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
|
||||
* which makes a Cryptoki API function pointer declaration or
|
||||
* function pointer type declaration out of a return type and a
|
||||
* function name. It should be used in the following fashion:
|
||||
*
|
||||
* // Define funcPtr to be a pointer to a Cryptoki API function
|
||||
* // taking arguments args and returning CK_RV.
|
||||
* CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
|
||||
*
|
||||
* or
|
||||
*
|
||||
* // Define funcPtrType to be the type of a pointer to a
|
||||
* // Cryptoki API function taking arguments args and returning
|
||||
* // CK_RV, and then define funcPtr to be a variable of type
|
||||
* // funcPtrType.
|
||||
* typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
|
||||
* funcPtrType funcPtr;
|
||||
*
|
||||
* If you're using Microsoft Developer Studio 5.0 to access
|
||||
* functions in a Win32 Cryptoki .dll, in might be defined by:
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
|
||||
* returnType __declspec(dllimport) (* name)
|
||||
*
|
||||
* If you're using an earlier version of Microsoft Developer
|
||||
* Studio to access functions in a Win16 Cryptoki .dll, it might
|
||||
* be defined by:
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
|
||||
* returnType __export _far _pascal (* name)
|
||||
*
|
||||
* In a UNIX environment, it might be defined by:
|
||||
*
|
||||
* #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
|
||||
* returnType (* name)
|
||||
*
|
||||
*
|
||||
* 4. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
|
||||
* a function pointer type for an application callback out of
|
||||
* a return type for the callback and a name for the callback.
|
||||
* It should be used in the following fashion:
|
||||
*
|
||||
* CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
|
||||
*
|
||||
* to declare a function pointer, myCallback, to a callback
|
||||
* which takes arguments args and returns a CK_RV. It can also
|
||||
* be used like this:
|
||||
*
|
||||
* typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
|
||||
* myCallbackType myCallback;
|
||||
*
|
||||
* If you're using Microsoft Developer Studio 5.0 to do Win32
|
||||
* Cryptoki development, it might be defined by:
|
||||
*
|
||||
* #define CK_CALLBACK_FUNCTION(returnType, name) \
|
||||
* returnType (* name)
|
||||
*
|
||||
* If you're using an earlier version of Microsoft Developer
|
||||
* Studio to do Win16 development, it might be defined by:
|
||||
*
|
||||
* #define CK_CALLBACK_FUNCTION(returnType, name) \
|
||||
* returnType _far _pascal (* name)
|
||||
*
|
||||
* In a UNIX environment, it might be defined by:
|
||||
*
|
||||
* #define CK_CALLBACK_FUNCTION(returnType, name) \
|
||||
* returnType (* name)
|
||||
*
|
||||
*
|
||||
* 5. NULL_PTR: This macro is the value of a NULL pointer.
|
||||
*
|
||||
* In any ANSI/ISO C environment (and in many others as well),
|
||||
* this should best be defined by
|
||||
*
|
||||
* #ifndef NULL_PTR
|
||||
* #define NULL_PTR 0
|
||||
* #endif
|
||||
*/
|
||||
|
||||
|
||||
/* All the various Cryptoki types and #define'd values are in the
|
||||
* file pkcs11t.h.
|
||||
*/
|
||||
#include "pkcs11t.h"
|
||||
|
||||
#define __PASTE(x,y) x##y
|
||||
|
||||
|
||||
/* ==============================================================
|
||||
* Define the "extern" form of all the entry points.
|
||||
* ==============================================================
|
||||
*/
|
||||
|
||||
#define CK_NEED_ARG_LIST 1
|
||||
#define CK_PKCS11_FUNCTION_INFO(name) \
|
||||
extern CK_DECLARE_FUNCTION(CK_RV, name)
|
||||
|
||||
/* pkcs11f.h has all the information about the Cryptoki
|
||||
* function prototypes.
|
||||
*/
|
||||
#include "pkcs11f.h"
|
||||
|
||||
#undef CK_NEED_ARG_LIST
|
||||
#undef CK_PKCS11_FUNCTION_INFO
|
||||
|
||||
|
||||
/* ==============================================================
|
||||
* Define the typedef form of all the entry points. That is, for
|
||||
* each Cryptoki function C_XXX, define a type CK_C_XXX which is
|
||||
* a pointer to that kind of function.
|
||||
* ==============================================================
|
||||
*/
|
||||
|
||||
#define CK_NEED_ARG_LIST 1
|
||||
#define CK_PKCS11_FUNCTION_INFO(name) \
|
||||
typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
|
||||
|
||||
/* pkcs11f.h has all the information about the Cryptoki
|
||||
* function prototypes.
|
||||
*/
|
||||
#include "pkcs11f.h"
|
||||
|
||||
#undef CK_NEED_ARG_LIST
|
||||
#undef CK_PKCS11_FUNCTION_INFO
|
||||
|
||||
|
||||
/* ==============================================================
|
||||
* Define structed vector of entry points. A CK_FUNCTION_LIST
|
||||
* contains a CK_VERSION indicating a library's Cryptoki version
|
||||
* and then a whole slew of function pointers to the routines in
|
||||
* the library. This type was declared, but not defined, in
|
||||
* pkcs11t.h.
|
||||
* ==============================================================
|
||||
*/
|
||||
|
||||
#define CK_PKCS11_FUNCTION_INFO(name) \
|
||||
__PASTE(CK_,name) name;
|
||||
|
||||
struct CK_FUNCTION_LIST {
|
||||
|
||||
CK_VERSION version; /* Cryptoki version */
|
||||
|
||||
/* Pile all the function pointers into the CK_FUNCTION_LIST. */
|
||||
/* pkcs11f.h has all the information about the Cryptoki
|
||||
* function prototypes.
|
||||
*/
|
||||
#include "pkcs11f.h"
|
||||
|
||||
};
|
||||
|
||||
#undef CK_PKCS11_FUNCTION_INFO
|
||||
|
||||
|
||||
#undef __PASTE
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PKCS11_H_ */
|
||||
|
939
vendor/github.com/miekg/pkcs11/pkcs11f.h
generated
vendored
Normal file
939
vendor/github.com/miekg/pkcs11/pkcs11f.h
generated
vendored
Normal file
@ -0,0 +1,939 @@
|
||||
/* Copyright (c) OASIS Open 2016. All Rights Reserved./
|
||||
* /Distributed under the terms of the OASIS IPR Policy,
|
||||
* [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
|
||||
* IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
|
||||
*/
|
||||
|
||||
/* Latest version of the specification:
|
||||
* http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
|
||||
*/
|
||||
|
||||
/* This header file contains pretty much everything about all the
|
||||
* Cryptoki function prototypes. Because this information is
|
||||
* used for more than just declaring function prototypes, the
|
||||
* order of the functions appearing herein is important, and
|
||||
* should not be altered.
|
||||
*/
|
||||
|
||||
/* General-purpose */
|
||||
|
||||
/* C_Initialize initializes the Cryptoki library. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Initialize)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
|
||||
* cast to CK_C_INITIALIZE_ARGS_PTR
|
||||
* and dereferenced
|
||||
*/
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Finalize indicates that an application is done with the
|
||||
* Cryptoki library.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_Finalize)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetInfo returns general information about Cryptoki. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetInfo)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_INFO_PTR pInfo /* location that receives information */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetFunctionList returns the function list. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
|
||||
* function list
|
||||
*/
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Slot and token management */
|
||||
|
||||
/* C_GetSlotList obtains a list of slots in the system. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_BBOOL tokenPresent, /* only slots with tokens */
|
||||
CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
|
||||
CK_ULONG_PTR pulCount /* receives number of slots */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetSlotInfo obtains information about a particular slot in
|
||||
* the system.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* the ID of the slot */
|
||||
CK_SLOT_INFO_PTR pInfo /* receives the slot information */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetTokenInfo obtains information about a particular token
|
||||
* in the system.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* ID of the token's slot */
|
||||
CK_TOKEN_INFO_PTR pInfo /* receives the token information */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetMechanismList obtains a list of mechanism types
|
||||
* supported by a token.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* ID of token's slot */
|
||||
CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
|
||||
CK_ULONG_PTR pulCount /* gets # of mechs. */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetMechanismInfo obtains information about a particular
|
||||
* mechanism possibly supported by a token.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* ID of the token's slot */
|
||||
CK_MECHANISM_TYPE type, /* type of mechanism */
|
||||
CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_InitToken initializes a token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_InitToken)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* ID of the token's slot */
|
||||
CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
|
||||
CK_ULONG ulPinLen, /* length in bytes of the PIN */
|
||||
CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_InitPIN initializes the normal user's PIN. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_InitPIN)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
|
||||
CK_ULONG ulPinLen /* length in bytes of the PIN */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SetPIN modifies the PIN of the user who is logged in. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_SetPIN)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
|
||||
CK_ULONG ulOldLen, /* length of the old PIN */
|
||||
CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
|
||||
CK_ULONG ulNewLen /* length of the new PIN */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Session management */
|
||||
|
||||
/* C_OpenSession opens a session between an application and a
|
||||
* token.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_OpenSession)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID, /* the slot's ID */
|
||||
CK_FLAGS flags, /* from CK_SESSION_INFO */
|
||||
CK_VOID_PTR pApplication, /* passed to callback */
|
||||
CK_NOTIFY Notify, /* callback function */
|
||||
CK_SESSION_HANDLE_PTR phSession /* gets session handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_CloseSession closes a session between an application and a
|
||||
* token.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_CloseSession)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession /* the session's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_CloseAllSessions closes all sessions with a token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SLOT_ID slotID /* the token's slot */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetSessionInfo obtains information about the session. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_SESSION_INFO_PTR pInfo /* receives session info */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetOperationState obtains the state of the cryptographic operation
|
||||
* in a session.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pOperationState, /* gets state */
|
||||
CK_ULONG_PTR pulOperationStateLen /* gets state length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SetOperationState restores the state of the cryptographic
|
||||
* operation in a session.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pOperationState, /* holds state */
|
||||
CK_ULONG ulOperationStateLen, /* holds state length */
|
||||
CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
|
||||
CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Login logs a user into a token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Login)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_USER_TYPE userType, /* the user type */
|
||||
CK_UTF8CHAR_PTR pPin, /* the user's PIN */
|
||||
CK_ULONG ulPinLen /* the length of the PIN */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Logout logs a user out from a token. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Logout)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession /* the session's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Object management */
|
||||
|
||||
/* C_CreateObject creates a new object. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_CreateObject)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
|
||||
CK_ULONG ulCount, /* attributes in template */
|
||||
CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_CopyObject copies an object, creating a new object for the
|
||||
* copy.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_CopyObject)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
|
||||
CK_ULONG ulCount, /* attributes in template */
|
||||
CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DestroyObject destroys an object. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject /* the object's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetObjectSize gets the size of an object in bytes. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ULONG_PTR pulSize /* receives size of object */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GetAttributeValue obtains the value of one or more object
|
||||
* attributes.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
|
||||
CK_ULONG ulCount /* attributes in template */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SetAttributeValue modifies the value of one or more object
|
||||
* attributes.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
|
||||
CK_ULONG ulCount /* attributes in template */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_FindObjectsInit initializes a search for token and session
|
||||
* objects that match a template.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
|
||||
CK_ULONG ulCount /* attrs in search template */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_FindObjects continues a search for token and session
|
||||
* objects that match a template, obtaining additional object
|
||||
* handles.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_FindObjects)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
|
||||
CK_ULONG ulMaxObjectCount, /* max handles to get */
|
||||
CK_ULONG_PTR pulObjectCount /* actual # returned */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_FindObjectsFinal finishes a search for token and session
|
||||
* objects.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession /* the session's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Encryption and decryption */
|
||||
|
||||
/* C_EncryptInit initializes an encryption operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* handle of encryption key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Encrypt encrypts single-part data. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Encrypt)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pData, /* the plaintext data */
|
||||
CK_ULONG ulDataLen, /* bytes of plaintext */
|
||||
CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
|
||||
CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_EncryptUpdate continues a multiple-part encryption
|
||||
* operation.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pPart, /* the plaintext data */
|
||||
CK_ULONG ulPartLen, /* plaintext data len */
|
||||
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
|
||||
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_EncryptFinal finishes a multiple-part encryption
|
||||
* operation.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session handle */
|
||||
CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
|
||||
CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DecryptInit initializes a decryption operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* handle of decryption key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Decrypt decrypts encrypted data in a single part. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Decrypt)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pEncryptedData, /* ciphertext */
|
||||
CK_ULONG ulEncryptedDataLen, /* ciphertext length */
|
||||
CK_BYTE_PTR pData, /* gets plaintext */
|
||||
CK_ULONG_PTR pulDataLen /* gets p-text size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DecryptUpdate continues a multiple-part decryption
|
||||
* operation.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pEncryptedPart, /* encrypted data */
|
||||
CK_ULONG ulEncryptedPartLen, /* input length */
|
||||
CK_BYTE_PTR pPart, /* gets plaintext */
|
||||
CK_ULONG_PTR pulPartLen /* p-text size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DecryptFinal finishes a multiple-part decryption
|
||||
* operation.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pLastPart, /* gets plaintext */
|
||||
CK_ULONG_PTR pulLastPartLen /* p-text size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Message digesting */
|
||||
|
||||
/* C_DigestInit initializes a message-digesting operation. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_DigestInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Digest digests data in a single part. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_Digest)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pData, /* data to be digested */
|
||||
CK_ULONG ulDataLen, /* bytes of data to digest */
|
||||
CK_BYTE_PTR pDigest, /* gets the message digest */
|
||||
CK_ULONG_PTR pulDigestLen /* gets digest length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DigestUpdate continues a multiple-part message-digesting
|
||||
* operation.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pPart, /* data to be digested */
|
||||
CK_ULONG ulPartLen /* bytes of data to be digested */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DigestKey continues a multi-part message-digesting
|
||||
* operation, by digesting the value of a secret key as part of
|
||||
* the data already digested.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_DigestKey)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hKey /* secret key to digest */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DigestFinal finishes a multiple-part message-digesting
|
||||
* operation.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pDigest, /* gets the message digest */
|
||||
CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Signing and MACing */
|
||||
|
||||
/* C_SignInit initializes a signature (private key encryption)
|
||||
* operation, where the signature is (will be) an appendix to
|
||||
* the data, and plaintext cannot be recovered from the
|
||||
* signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* handle of signature key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Sign signs (encrypts with private key) data in a single
|
||||
* part, where the signature is (will be) an appendix to the
|
||||
* data, and plaintext cannot be recovered from the signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_Sign)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pData, /* the data to sign */
|
||||
CK_ULONG ulDataLen, /* count of bytes to sign */
|
||||
CK_BYTE_PTR pSignature, /* gets the signature */
|
||||
CK_ULONG_PTR pulSignatureLen /* gets signature length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SignUpdate continues a multiple-part signature operation,
|
||||
* where the signature is (will be) an appendix to the data,
|
||||
* and plaintext cannot be recovered from the signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pPart, /* the data to sign */
|
||||
CK_ULONG ulPartLen /* count of bytes to sign */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SignFinal finishes a multiple-part signature operation,
|
||||
* returning the signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pSignature, /* gets the signature */
|
||||
CK_ULONG_PTR pulSignatureLen /* gets signature length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SignRecoverInit initializes a signature operation, where
|
||||
* the data can be recovered from the signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* handle of the signature key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SignRecover signs data in a single operation, where the
|
||||
* data can be recovered from the signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignRecover)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pData, /* the data to sign */
|
||||
CK_ULONG ulDataLen, /* count of bytes to sign */
|
||||
CK_BYTE_PTR pSignature, /* gets the signature */
|
||||
CK_ULONG_PTR pulSignatureLen /* gets signature length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Verifying signatures and MACs */
|
||||
|
||||
/* C_VerifyInit initializes a verification operation, where the
|
||||
* signature is an appendix to the data, and plaintext cannot
|
||||
* cannot be recovered from the signature (e.g. DSA).
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* verification key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_Verify verifies a signature in a single-part operation,
|
||||
* where the signature is an appendix to the data, and plaintext
|
||||
* cannot be recovered from the signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_Verify)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pData, /* signed data */
|
||||
CK_ULONG ulDataLen, /* length of signed data */
|
||||
CK_BYTE_PTR pSignature, /* signature */
|
||||
CK_ULONG ulSignatureLen /* signature length*/
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_VerifyUpdate continues a multiple-part verification
|
||||
* operation, where the signature is an appendix to the data,
|
||||
* and plaintext cannot be recovered from the signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pPart, /* signed data */
|
||||
CK_ULONG ulPartLen /* length of signed data */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_VerifyFinal finishes a multiple-part verification
|
||||
* operation, checking the signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pSignature, /* signature to verify */
|
||||
CK_ULONG ulSignatureLen /* signature length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_VerifyRecoverInit initializes a signature verification
|
||||
* operation, where the data is recovered from the signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
|
||||
CK_OBJECT_HANDLE hKey /* verification key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_VerifyRecover verifies a signature in a single-part
|
||||
* operation, where the data is recovered from the signature.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pSignature, /* signature to verify */
|
||||
CK_ULONG ulSignatureLen, /* signature length */
|
||||
CK_BYTE_PTR pData, /* gets signed data */
|
||||
CK_ULONG_PTR pulDataLen /* gets signed data len */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Dual-function cryptographic operations */
|
||||
|
||||
/* C_DigestEncryptUpdate continues a multiple-part digesting
|
||||
* and encryption operation.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pPart, /* the plaintext data */
|
||||
CK_ULONG ulPartLen, /* plaintext length */
|
||||
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
|
||||
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DecryptDigestUpdate continues a multiple-part decryption and
|
||||
* digesting operation.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pEncryptedPart, /* ciphertext */
|
||||
CK_ULONG ulEncryptedPartLen, /* ciphertext length */
|
||||
CK_BYTE_PTR pPart, /* gets plaintext */
|
||||
CK_ULONG_PTR pulPartLen /* gets plaintext len */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_SignEncryptUpdate continues a multiple-part signing and
|
||||
* encryption operation.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pPart, /* the plaintext data */
|
||||
CK_ULONG ulPartLen, /* plaintext length */
|
||||
CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
|
||||
CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DecryptVerifyUpdate continues a multiple-part decryption and
|
||||
* verify operation.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_BYTE_PTR pEncryptedPart, /* ciphertext */
|
||||
CK_ULONG ulEncryptedPartLen, /* ciphertext length */
|
||||
CK_BYTE_PTR pPart, /* gets plaintext */
|
||||
CK_ULONG_PTR pulPartLen /* gets p-text length */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Key management */
|
||||
|
||||
/* C_GenerateKey generates a secret key, creating a new key
|
||||
* object.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* key generation mech. */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
|
||||
CK_ULONG ulCount, /* # of attrs in template */
|
||||
CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GenerateKeyPair generates a public-key/private-key pair,
|
||||
* creating new key objects.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* key-gen mech. */
|
||||
CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template for pub. key */
|
||||
CK_ULONG ulPublicKeyAttributeCount, /* # pub. attrs. */
|
||||
CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template for priv. key */
|
||||
CK_ULONG ulPrivateKeyAttributeCount, /* # priv. attrs. */
|
||||
CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. key handle */
|
||||
CK_OBJECT_HANDLE_PTR phPrivateKey /* gets priv. key handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_WrapKey wraps (i.e., encrypts) a key. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_WrapKey)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
|
||||
CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
|
||||
CK_OBJECT_HANDLE hKey, /* key to be wrapped */
|
||||
CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
|
||||
CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
|
||||
* key object.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
|
||||
CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
|
||||
CK_BYTE_PTR pWrappedKey, /* the wrapped key */
|
||||
CK_ULONG ulWrappedKeyLen, /* wrapped key len */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* new key template */
|
||||
CK_ULONG ulAttributeCount, /* template length */
|
||||
CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_DeriveKey derives a key from a base key, creating a new key
|
||||
* object.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
|
||||
CK_OBJECT_HANDLE hBaseKey, /* base key */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* new key template */
|
||||
CK_ULONG ulAttributeCount, /* template length */
|
||||
CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Random number generation */
|
||||
|
||||
/* C_SeedRandom mixes additional seed material into the token's
|
||||
* random number generator.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pSeed, /* the seed material */
|
||||
CK_ULONG ulSeedLen /* length of seed material */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_GenerateRandom generates random data. */
|
||||
CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR RandomData, /* receives the random data */
|
||||
CK_ULONG ulRandomLen /* # of bytes to generate */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Parallel function management */
|
||||
|
||||
/* C_GetFunctionStatus is a legacy function; it obtains an
|
||||
* updated status of a function running in parallel with an
|
||||
* application.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession /* the session's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_CancelFunction is a legacy function; it cancels a function
|
||||
* running in parallel.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_SESSION_HANDLE hSession /* the session's handle */
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/* C_WaitForSlotEvent waits for a slot event (token insertion,
|
||||
* removal, etc.) to occur.
|
||||
*/
|
||||
CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
|
||||
#ifdef CK_NEED_ARG_LIST
|
||||
(
|
||||
CK_FLAGS flags, /* blocking/nonblocking flag */
|
||||
CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
|
||||
CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
|
||||
);
|
||||
#endif
|
||||
|
33
vendor/github.com/miekg/pkcs11/pkcs11go.h
generated
vendored
Normal file
33
vendor/github.com/miekg/pkcs11/pkcs11go.h
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
|
||||
#define CK_PTR *
|
||||
#ifndef NULL_PTR
|
||||
#define NULL_PTR 0
|
||||
#endif
|
||||
#define CK_DEFINE_FUNCTION(returnType, name) returnType name
|
||||
#define CK_DECLARE_FUNCTION(returnType, name) returnType name
|
||||
#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
|
||||
#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
|
||||
|
||||
#include <unistd.h>
|
||||
#ifdef PACKED_STRUCTURES
|
||||
# pragma pack(push, 1)
|
||||
# include "pkcs11.h"
|
||||
# pragma pack(pop)
|
||||
#else
|
||||
# include "pkcs11.h"
|
||||
#endif
|
||||
|
||||
// Copy of CK_INFO but with default alignment (not packed). Go hides unaligned
|
||||
// struct fields so copying to an aligned struct is necessary to read CK_INFO
|
||||
// from Go on Windows where packing is required.
|
||||
typedef struct ckInfo {
|
||||
CK_VERSION cryptokiVersion;
|
||||
CK_UTF8CHAR manufacturerID[32];
|
||||
CK_FLAGS flags;
|
||||
CK_UTF8CHAR libraryDescription[32];
|
||||
CK_VERSION libraryVersion;
|
||||
} ckInfo, *ckInfoPtr;
|
2047
vendor/github.com/miekg/pkcs11/pkcs11t.h
generated
vendored
Normal file
2047
vendor/github.com/miekg/pkcs11/pkcs11t.h
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
18
vendor/github.com/miekg/pkcs11/release.go
generated
vendored
Normal file
18
vendor/github.com/miekg/pkcs11/release.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
//go:build release
|
||||
// +build release
|
||||
|
||||
package pkcs11
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Release is current version of the pkcs11 library.
|
||||
var Release = R{1, 1, 1}
|
||||
|
||||
// R holds the version of this library.
|
||||
type R struct {
|
||||
Major, Minor, Patch int
|
||||
}
|
||||
|
||||
func (r R) String() string {
|
||||
return fmt.Sprintf("%d.%d.%d", r.Major, r.Minor, r.Patch)
|
||||
}
|
1
vendor/github.com/miekg/pkcs11/softhsm.conf
generated
vendored
Normal file
1
vendor/github.com/miekg/pkcs11/softhsm.conf
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
0:hsm.db
|
4
vendor/github.com/miekg/pkcs11/softhsm2.conf
generated
vendored
Normal file
4
vendor/github.com/miekg/pkcs11/softhsm2.conf
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
log.level = INFO
|
||||
objectstore.backend = file
|
||||
directories.tokendir = test_data
|
||||
slots.removable = false
|
315
vendor/github.com/miekg/pkcs11/types.go
generated
vendored
Normal file
315
vendor/github.com/miekg/pkcs11/types.go
generated
vendored
Normal file
@ -0,0 +1,315 @@
|
||||
// Copyright 2013 Miek Gieben. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pkcs11
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pkcs11go.h"
|
||||
|
||||
CK_ULONG Index(CK_ULONG_PTR array, CK_ULONG i)
|
||||
{
|
||||
return array[i];
|
||||
}
|
||||
|
||||
static inline void putAttributePval(CK_ATTRIBUTE_PTR a, CK_VOID_PTR pValue)
|
||||
{
|
||||
a->pValue = pValue;
|
||||
}
|
||||
|
||||
static inline void putMechanismParam(CK_MECHANISM_PTR m, CK_VOID_PTR pParameter)
|
||||
{
|
||||
m->pParameter = pParameter;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type arena []unsafe.Pointer
|
||||
|
||||
func (a *arena) Allocate(obj []byte) (C.CK_VOID_PTR, C.CK_ULONG) {
|
||||
cobj := C.calloc(C.size_t(len(obj)), 1)
|
||||
*a = append(*a, cobj)
|
||||
C.memmove(cobj, unsafe.Pointer(&obj[0]), C.size_t(len(obj)))
|
||||
return C.CK_VOID_PTR(cobj), C.CK_ULONG(len(obj))
|
||||
}
|
||||
|
||||
func (a arena) Free() {
|
||||
for _, p := range a {
|
||||
C.free(p)
|
||||
}
|
||||
}
|
||||
|
||||
// toList converts from a C style array to a []uint.
|
||||
func toList(clist C.CK_ULONG_PTR, size C.CK_ULONG) []uint {
|
||||
l := make([]uint, int(size))
|
||||
for i := 0; i < len(l); i++ {
|
||||
l[i] = uint(C.Index(clist, C.CK_ULONG(i)))
|
||||
}
|
||||
defer C.free(unsafe.Pointer(clist))
|
||||
return l
|
||||
}
|
||||
|
||||
// cBBool converts a bool to a CK_BBOOL.
|
||||
func cBBool(x bool) C.CK_BBOOL {
|
||||
if x {
|
||||
return C.CK_BBOOL(C.CK_TRUE)
|
||||
}
|
||||
return C.CK_BBOOL(C.CK_FALSE)
|
||||
}
|
||||
|
||||
func uintToBytes(x uint64) []byte {
|
||||
ul := C.CK_ULONG(x)
|
||||
return C.GoBytes(unsafe.Pointer(&ul), C.int(unsafe.Sizeof(ul)))
|
||||
}
|
||||
|
||||
// Error represents an PKCS#11 error.
|
||||
type Error uint
|
||||
|
||||
func (e Error) Error() string {
|
||||
return fmt.Sprintf("pkcs11: 0x%X: %s", uint(e), strerror[uint(e)])
|
||||
}
|
||||
|
||||
func toError(e C.CK_RV) error {
|
||||
if e == C.CKR_OK {
|
||||
return nil
|
||||
}
|
||||
return Error(e)
|
||||
}
|
||||
|
||||
// SessionHandle is a Cryptoki-assigned value that identifies a session.
|
||||
type SessionHandle uint
|
||||
|
||||
// ObjectHandle is a token-specific identifier for an object.
|
||||
type ObjectHandle uint
|
||||
|
||||
// Version represents any version information from the library.
|
||||
type Version struct {
|
||||
Major byte
|
||||
Minor byte
|
||||
}
|
||||
|
||||
func toVersion(version C.CK_VERSION) Version {
|
||||
return Version{byte(version.major), byte(version.minor)}
|
||||
}
|
||||
|
||||
// SlotEvent holds the SlotID which for which an slot event (token insertion,
|
||||
// removal, etc.) occurred.
|
||||
type SlotEvent struct {
|
||||
SlotID uint
|
||||
}
|
||||
|
||||
// Info provides information about the library and hardware used.
|
||||
type Info struct {
|
||||
CryptokiVersion Version
|
||||
ManufacturerID string
|
||||
Flags uint
|
||||
LibraryDescription string
|
||||
LibraryVersion Version
|
||||
}
|
||||
|
||||
// SlotInfo provides information about a slot.
|
||||
type SlotInfo struct {
|
||||
SlotDescription string // 64 bytes.
|
||||
ManufacturerID string // 32 bytes.
|
||||
Flags uint
|
||||
HardwareVersion Version
|
||||
FirmwareVersion Version
|
||||
}
|
||||
|
||||
// TokenInfo provides information about a token.
|
||||
type TokenInfo struct {
|
||||
Label string
|
||||
ManufacturerID string
|
||||
Model string
|
||||
SerialNumber string
|
||||
Flags uint
|
||||
MaxSessionCount uint
|
||||
SessionCount uint
|
||||
MaxRwSessionCount uint
|
||||
RwSessionCount uint
|
||||
MaxPinLen uint
|
||||
MinPinLen uint
|
||||
TotalPublicMemory uint
|
||||
FreePublicMemory uint
|
||||
TotalPrivateMemory uint
|
||||
FreePrivateMemory uint
|
||||
HardwareVersion Version
|
||||
FirmwareVersion Version
|
||||
UTCTime string
|
||||
}
|
||||
|
||||
// SessionInfo provides information about a session.
|
||||
type SessionInfo struct {
|
||||
SlotID uint
|
||||
State uint
|
||||
Flags uint
|
||||
DeviceError uint
|
||||
}
|
||||
|
||||
// Attribute holds an attribute type/value combination.
|
||||
type Attribute struct {
|
||||
Type uint
|
||||
Value []byte
|
||||
}
|
||||
|
||||
// NewAttribute allocates a Attribute and returns a pointer to it.
|
||||
// Note that this is merely a convenience function, as values returned
|
||||
// from the HSM are not converted back to Go values, those are just raw
|
||||
// byte slices.
|
||||
func NewAttribute(typ uint, x interface{}) *Attribute {
|
||||
// This function nicely transforms *to* an attribute, but there is
|
||||
// no corresponding function that transform back *from* an attribute,
|
||||
// which in PKCS#11 is just an byte array.
|
||||
a := new(Attribute)
|
||||
a.Type = typ
|
||||
if x == nil {
|
||||
return a
|
||||
}
|
||||
switch v := x.(type) {
|
||||
case bool:
|
||||
if v {
|
||||
a.Value = []byte{1}
|
||||
} else {
|
||||
a.Value = []byte{0}
|
||||
}
|
||||
case int:
|
||||
a.Value = uintToBytes(uint64(v))
|
||||
case int16:
|
||||
a.Value = uintToBytes(uint64(v))
|
||||
case int32:
|
||||
a.Value = uintToBytes(uint64(v))
|
||||
case int64:
|
||||
a.Value = uintToBytes(uint64(v))
|
||||
case uint:
|
||||
a.Value = uintToBytes(uint64(v))
|
||||
case uint16:
|
||||
a.Value = uintToBytes(uint64(v))
|
||||
case uint32:
|
||||
a.Value = uintToBytes(uint64(v))
|
||||
case uint64:
|
||||
a.Value = uintToBytes(uint64(v))
|
||||
case string:
|
||||
a.Value = []byte(v)
|
||||
case []byte:
|
||||
a.Value = v
|
||||
case time.Time: // for CKA_DATE
|
||||
a.Value = cDate(v)
|
||||
default:
|
||||
panic("pkcs11: unhandled attribute type")
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// cAttribute returns the start address and the length of an attribute list.
|
||||
func cAttributeList(a []*Attribute) (arena, C.CK_ATTRIBUTE_PTR, C.CK_ULONG) {
|
||||
var arena arena
|
||||
if len(a) == 0 {
|
||||
return nil, nil, 0
|
||||
}
|
||||
pa := make([]C.CK_ATTRIBUTE, len(a))
|
||||
for i, attr := range a {
|
||||
pa[i]._type = C.CK_ATTRIBUTE_TYPE(attr.Type)
|
||||
if len(attr.Value) != 0 {
|
||||
buf, len := arena.Allocate(attr.Value)
|
||||
// field is unaligned on windows so this has to call into C
|
||||
C.putAttributePval(&pa[i], buf)
|
||||
pa[i].ulValueLen = len
|
||||
}
|
||||
}
|
||||
return arena, &pa[0], C.CK_ULONG(len(a))
|
||||
}
|
||||
|
||||
func cDate(t time.Time) []byte {
|
||||
b := make([]byte, 8)
|
||||
year, month, day := t.Date()
|
||||
y := fmt.Sprintf("%4d", year)
|
||||
m := fmt.Sprintf("%02d", month)
|
||||
d1 := fmt.Sprintf("%02d", day)
|
||||
b[0], b[1], b[2], b[3] = y[0], y[1], y[2], y[3]
|
||||
b[4], b[5] = m[0], m[1]
|
||||
b[6], b[7] = d1[0], d1[1]
|
||||
return b
|
||||
}
|
||||
|
||||
// Mechanism holds an mechanism type/value combination.
|
||||
type Mechanism struct {
|
||||
Mechanism uint
|
||||
Parameter []byte
|
||||
generator interface{}
|
||||
}
|
||||
|
||||
// NewMechanism returns a pointer to an initialized Mechanism.
|
||||
func NewMechanism(mech uint, x interface{}) *Mechanism {
|
||||
m := new(Mechanism)
|
||||
m.Mechanism = mech
|
||||
if x == nil {
|
||||
return m
|
||||
}
|
||||
|
||||
switch p := x.(type) {
|
||||
case *GCMParams, *OAEPParams, *ECDH1DeriveParams:
|
||||
// contains pointers; defer serialization until cMechanism
|
||||
m.generator = p
|
||||
case []byte:
|
||||
m.Parameter = p
|
||||
default:
|
||||
panic("parameter must be one of type: []byte, *GCMParams, *OAEPParams, *ECDH1DeriveParams")
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func cMechanism(mechList []*Mechanism) (arena, *C.CK_MECHANISM) {
|
||||
if len(mechList) != 1 {
|
||||
panic("expected exactly one mechanism")
|
||||
}
|
||||
mech := mechList[0]
|
||||
cmech := &C.CK_MECHANISM{mechanism: C.CK_MECHANISM_TYPE(mech.Mechanism)}
|
||||
// params that contain pointers are allocated here
|
||||
param := mech.Parameter
|
||||
var arena arena
|
||||
switch p := mech.generator.(type) {
|
||||
case *GCMParams:
|
||||
// uses its own arena because it has to outlive this function call (yuck)
|
||||
param = cGCMParams(p)
|
||||
case *OAEPParams:
|
||||
param, arena = cOAEPParams(p, arena)
|
||||
case *ECDH1DeriveParams:
|
||||
param, arena = cECDH1DeriveParams(p, arena)
|
||||
}
|
||||
if len(param) != 0 {
|
||||
buf, len := arena.Allocate(param)
|
||||
// field is unaligned on windows so this has to call into C
|
||||
C.putMechanismParam(cmech, buf)
|
||||
cmech.ulParameterLen = len
|
||||
}
|
||||
return arena, cmech
|
||||
}
|
||||
|
||||
// MechanismInfo provides information about a particular mechanism.
|
||||
type MechanismInfo struct {
|
||||
MinKeySize uint
|
||||
MaxKeySize uint
|
||||
Flags uint
|
||||
}
|
||||
|
||||
// stubData is a persistent nonempty byte array used by cMessage.
|
||||
var stubData = []byte{0}
|
||||
|
||||
// cMessage returns the pointer/length pair corresponding to data.
|
||||
func cMessage(data []byte) (dataPtr C.CK_BYTE_PTR) {
|
||||
l := len(data)
|
||||
if l == 0 {
|
||||
// &data[0] is forbidden in this case, so use a nontrivial array instead.
|
||||
data = stubData
|
||||
}
|
||||
return C.CK_BYTE_PTR(unsafe.Pointer(&data[0]))
|
||||
}
|
127
vendor/github.com/miekg/pkcs11/vendor.go
generated
vendored
Normal file
127
vendor/github.com/miekg/pkcs11/vendor.go
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
package pkcs11
|
||||
|
||||
// Vendor specific range for Ncipher network HSM.
|
||||
const (
|
||||
NFCK_VENDOR_NCIPHER = 0xde436972
|
||||
CKA_NCIPHER = NFCK_VENDOR_NCIPHER
|
||||
CKM_NCIPHER = NFCK_VENDOR_NCIPHER
|
||||
CKK_NCIPHER = NFCK_VENDOR_NCIPHER
|
||||
)
|
||||
|
||||
// Vendor specific mechanisms for HMAC on Ncipher HSMs where Ncipher does not allow use of generic_secret keys.
|
||||
const (
|
||||
CKM_NC_SHA_1_HMAC_KEY_GEN = CKM_NCIPHER + 0x3 /* no params */
|
||||
CKM_NC_MD5_HMAC_KEY_GEN = CKM_NCIPHER + 0x6 /* no params */
|
||||
CKM_NC_SHA224_HMAC_KEY_GEN = CKM_NCIPHER + 0x24 /* no params */
|
||||
CKM_NC_SHA256_HMAC_KEY_GEN = CKM_NCIPHER + 0x25 /* no params */
|
||||
CKM_NC_SHA384_HMAC_KEY_GEN = CKM_NCIPHER + 0x26 /* no params */
|
||||
CKM_NC_SHA512_HMAC_KEY_GEN = CKM_NCIPHER + 0x27 /* no params */
|
||||
)
|
||||
|
||||
// Vendor specific range for Mozilla NSS.
|
||||
const (
|
||||
NSSCK_VENDOR_NSS = 0x4E534350
|
||||
CKO_NSS = CKO_VENDOR_DEFINED | NSSCK_VENDOR_NSS
|
||||
CKK_NSS = CKK_VENDOR_DEFINED | NSSCK_VENDOR_NSS
|
||||
CKC_NSS = CKC_VENDOR_DEFINED | NSSCK_VENDOR_NSS
|
||||
CKA_NSS = CKA_VENDOR_DEFINED | NSSCK_VENDOR_NSS
|
||||
CKA_TRUST = CKA_NSS + 0x2000
|
||||
CKM_NSS = CKM_VENDOR_DEFINED | NSSCK_VENDOR_NSS
|
||||
CKR_NSS = CKM_VENDOR_DEFINED | NSSCK_VENDOR_NSS
|
||||
CKT_VENDOR_DEFINED = 0x80000000
|
||||
CKT_NSS = CKT_VENDOR_DEFINED | NSSCK_VENDOR_NSS
|
||||
)
|
||||
|
||||
// Vendor specific values for Mozilla NSS.
|
||||
const (
|
||||
CKO_NSS_CRL = CKO_NSS + 1
|
||||
CKO_NSS_SMIME = CKO_NSS + 2
|
||||
CKO_NSS_TRUST = CKO_NSS + 3
|
||||
CKO_NSS_BUILTIN_ROOT_LIST = CKO_NSS + 4
|
||||
CKO_NSS_NEWSLOT = CKO_NSS + 5
|
||||
CKO_NSS_DELSLOT = CKO_NSS + 6
|
||||
CKK_NSS_PKCS8 = CKK_NSS + 1
|
||||
CKK_NSS_JPAKE_ROUND1 = CKK_NSS + 2
|
||||
CKK_NSS_JPAKE_ROUND2 = CKK_NSS + 3
|
||||
CKK_NSS_CHACHA20 = CKK_NSS + 4
|
||||
CKA_NSS_URL = CKA_NSS + 1
|
||||
CKA_NSS_EMAIL = CKA_NSS + 2
|
||||
CKA_NSS_SMIME_INFO = CKA_NSS + 3
|
||||
CKA_NSS_SMIME_TIMESTAMP = CKA_NSS + 4
|
||||
CKA_NSS_PKCS8_SALT = CKA_NSS + 5
|
||||
CKA_NSS_PASSWORD_CHECK = CKA_NSS + 6
|
||||
CKA_NSS_EXPIRES = CKA_NSS + 7
|
||||
CKA_NSS_KRL = CKA_NSS + 8
|
||||
CKA_NSS_PQG_COUNTER = CKA_NSS + 20
|
||||
CKA_NSS_PQG_SEED = CKA_NSS + 21
|
||||
CKA_NSS_PQG_H = CKA_NSS + 22
|
||||
CKA_NSS_PQG_SEED_BITS = CKA_NSS + 23
|
||||
CKA_NSS_MODULE_SPEC = CKA_NSS + 24
|
||||
CKA_NSS_OVERRIDE_EXTENSIONS = CKA_NSS + 25
|
||||
CKA_NSS_JPAKE_SIGNERID = CKA_NSS + 26
|
||||
CKA_NSS_JPAKE_PEERID = CKA_NSS + 27
|
||||
CKA_NSS_JPAKE_GX1 = CKA_NSS + 28
|
||||
CKA_NSS_JPAKE_GX2 = CKA_NSS + 29
|
||||
CKA_NSS_JPAKE_GX3 = CKA_NSS + 30
|
||||
CKA_NSS_JPAKE_GX4 = CKA_NSS + 31
|
||||
CKA_NSS_JPAKE_X2 = CKA_NSS + 32
|
||||
CKA_NSS_JPAKE_X2S = CKA_NSS + 33
|
||||
CKA_NSS_MOZILLA_CA_POLICY = CKA_NSS + 34
|
||||
CKA_TRUST_DIGITAL_SIGNATURE = CKA_TRUST + 1
|
||||
CKA_TRUST_NON_REPUDIATION = CKA_TRUST + 2
|
||||
CKA_TRUST_KEY_ENCIPHERMENT = CKA_TRUST + 3
|
||||
CKA_TRUST_DATA_ENCIPHERMENT = CKA_TRUST + 4
|
||||
CKA_TRUST_KEY_AGREEMENT = CKA_TRUST + 5
|
||||
CKA_TRUST_KEY_CERT_SIGN = CKA_TRUST + 6
|
||||
CKA_TRUST_CRL_SIGN = CKA_TRUST + 7
|
||||
CKA_TRUST_SERVER_AUTH = CKA_TRUST + 8
|
||||
CKA_TRUST_CLIENT_AUTH = CKA_TRUST + 9
|
||||
CKA_TRUST_CODE_SIGNING = CKA_TRUST + 10
|
||||
CKA_TRUST_EMAIL_PROTECTION = CKA_TRUST + 11
|
||||
CKA_TRUST_IPSEC_END_SYSTEM = CKA_TRUST + 12
|
||||
CKA_TRUST_IPSEC_TUNNEL = CKA_TRUST + 13
|
||||
CKA_TRUST_IPSEC_USER = CKA_TRUST + 14
|
||||
CKA_TRUST_TIME_STAMPING = CKA_TRUST + 15
|
||||
CKA_TRUST_STEP_UP_APPROVED = CKA_TRUST + 16
|
||||
CKA_CERT_SHA1_HASH = CKA_TRUST + 100
|
||||
CKA_CERT_MD5_HASH = CKA_TRUST + 101
|
||||
CKM_NSS_AES_KEY_WRAP = CKM_NSS + 1
|
||||
CKM_NSS_AES_KEY_WRAP_PAD = CKM_NSS + 2
|
||||
CKM_NSS_HKDF_SHA1 = CKM_NSS + 3
|
||||
CKM_NSS_HKDF_SHA256 = CKM_NSS + 4
|
||||
CKM_NSS_HKDF_SHA384 = CKM_NSS + 5
|
||||
CKM_NSS_HKDF_SHA512 = CKM_NSS + 6
|
||||
CKM_NSS_JPAKE_ROUND1_SHA1 = CKM_NSS + 7
|
||||
CKM_NSS_JPAKE_ROUND1_SHA256 = CKM_NSS + 8
|
||||
CKM_NSS_JPAKE_ROUND1_SHA384 = CKM_NSS + 9
|
||||
CKM_NSS_JPAKE_ROUND1_SHA512 = CKM_NSS + 10
|
||||
CKM_NSS_JPAKE_ROUND2_SHA1 = CKM_NSS + 11
|
||||
CKM_NSS_JPAKE_ROUND2_SHA256 = CKM_NSS + 12
|
||||
CKM_NSS_JPAKE_ROUND2_SHA384 = CKM_NSS + 13
|
||||
CKM_NSS_JPAKE_ROUND2_SHA512 = CKM_NSS + 14
|
||||
CKM_NSS_JPAKE_FINAL_SHA1 = CKM_NSS + 15
|
||||
CKM_NSS_JPAKE_FINAL_SHA256 = CKM_NSS + 16
|
||||
CKM_NSS_JPAKE_FINAL_SHA384 = CKM_NSS + 17
|
||||
CKM_NSS_JPAKE_FINAL_SHA512 = CKM_NSS + 18
|
||||
CKM_NSS_HMAC_CONSTANT_TIME = CKM_NSS + 19
|
||||
CKM_NSS_SSL3_MAC_CONSTANT_TIME = CKM_NSS + 20
|
||||
CKM_NSS_TLS_PRF_GENERAL_SHA256 = CKM_NSS + 21
|
||||
CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256 = CKM_NSS + 22
|
||||
CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256 = CKM_NSS + 23
|
||||
CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 = CKM_NSS + 24
|
||||
CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE = CKM_NSS + 25
|
||||
CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH = CKM_NSS + 26
|
||||
CKM_NSS_CHACHA20_KEY_GEN = CKM_NSS + 27
|
||||
CKM_NSS_CHACHA20_POLY1305 = CKM_NSS + 28
|
||||
CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN = CKM_NSS + 29
|
||||
CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN = CKM_NSS + 30
|
||||
CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN = CKM_NSS + 31
|
||||
CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN = CKM_NSS + 32
|
||||
CKR_NSS_CERTDB_FAILED = CKR_NSS + 1
|
||||
CKR_NSS_KEYDB_FAILED = CKR_NSS + 2
|
||||
CKT_NSS_TRUSTED = CKT_NSS + 1
|
||||
CKT_NSS_TRUSTED_DELEGATOR = CKT_NSS + 2
|
||||
CKT_NSS_MUST_VERIFY_TRUST = CKT_NSS + 3
|
||||
CKT_NSS_NOT_TRUSTED = CKT_NSS + 10
|
||||
CKT_NSS_TRUST_UNKNOWN = CKT_NSS + 5
|
||||
)
|
766
vendor/github.com/miekg/pkcs11/zconst.go
generated
vendored
Normal file
766
vendor/github.com/miekg/pkcs11/zconst.go
generated
vendored
Normal file
@ -0,0 +1,766 @@
|
||||
// Copyright 2013 Miek Gieben. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Code generated by "go run const_generate.go"; DO NOT EDIT.
|
||||
|
||||
package pkcs11
|
||||
|
||||
const (
|
||||
CK_TRUE = 1
|
||||
CK_FALSE = 0
|
||||
CK_UNAVAILABLE_INFORMATION = ^uint(0)
|
||||
CK_EFFECTIVELY_INFINITE = 0
|
||||
CK_INVALID_HANDLE = 0
|
||||
CKN_SURRENDER = 0
|
||||
CKN_OTP_CHANGED = 1
|
||||
CKF_TOKEN_PRESENT = 0x00000001
|
||||
CKF_REMOVABLE_DEVICE = 0x00000002
|
||||
CKF_HW_SLOT = 0x00000004
|
||||
CKF_RNG = 0x00000001
|
||||
CKF_WRITE_PROTECTED = 0x00000002
|
||||
CKF_LOGIN_REQUIRED = 0x00000004
|
||||
CKF_USER_PIN_INITIALIZED = 0x00000008
|
||||
CKF_RESTORE_KEY_NOT_NEEDED = 0x00000020
|
||||
CKF_CLOCK_ON_TOKEN = 0x00000040
|
||||
CKF_PROTECTED_AUTHENTICATION_PATH = 0x00000100
|
||||
CKF_DUAL_CRYPTO_OPERATIONS = 0x00000200
|
||||
CKF_TOKEN_INITIALIZED = 0x00000400
|
||||
CKF_SECONDARY_AUTHENTICATION = 0x00000800
|
||||
CKF_USER_PIN_COUNT_LOW = 0x00010000
|
||||
CKF_USER_PIN_FINAL_TRY = 0x00020000
|
||||
CKF_USER_PIN_LOCKED = 0x00040000
|
||||
CKF_USER_PIN_TO_BE_CHANGED = 0x00080000
|
||||
CKF_SO_PIN_COUNT_LOW = 0x00100000
|
||||
CKF_SO_PIN_FINAL_TRY = 0x00200000
|
||||
CKF_SO_PIN_LOCKED = 0x00400000
|
||||
CKF_SO_PIN_TO_BE_CHANGED = 0x00800000
|
||||
CKF_ERROR_STATE = 0x01000000
|
||||
CKU_SO = 0
|
||||
CKU_USER = 1
|
||||
CKU_CONTEXT_SPECIFIC = 2
|
||||
CKS_RO_PUBLIC_SESSION = 0
|
||||
CKS_RO_USER_FUNCTIONS = 1
|
||||
CKS_RW_PUBLIC_SESSION = 2
|
||||
CKS_RW_USER_FUNCTIONS = 3
|
||||
CKS_RW_SO_FUNCTIONS = 4
|
||||
CKF_RW_SESSION = 0x00000002
|
||||
CKF_SERIAL_SESSION = 0x00000004
|
||||
CKO_DATA = 0x00000000
|
||||
CKO_CERTIFICATE = 0x00000001
|
||||
CKO_PUBLIC_KEY = 0x00000002
|
||||
CKO_PRIVATE_KEY = 0x00000003
|
||||
CKO_SECRET_KEY = 0x00000004
|
||||
CKO_HW_FEATURE = 0x00000005
|
||||
CKO_DOMAIN_PARAMETERS = 0x00000006
|
||||
CKO_MECHANISM = 0x00000007
|
||||
CKO_OTP_KEY = 0x00000008
|
||||
CKO_VENDOR_DEFINED = 0x80000000
|
||||
CKH_MONOTONIC_COUNTER = 0x00000001
|
||||
CKH_CLOCK = 0x00000002
|
||||
CKH_USER_INTERFACE = 0x00000003
|
||||
CKH_VENDOR_DEFINED = 0x80000000
|
||||
CKK_RSA = 0x00000000
|
||||
CKK_DSA = 0x00000001
|
||||
CKK_DH = 0x00000002
|
||||
CKK_ECDSA = 0x00000003 // Deprecated
|
||||
CKK_EC = 0x00000003
|
||||
CKK_X9_42_DH = 0x00000004
|
||||
CKK_KEA = 0x00000005
|
||||
CKK_GENERIC_SECRET = 0x00000010
|
||||
CKK_RC2 = 0x00000011
|
||||
CKK_RC4 = 0x00000012
|
||||
CKK_DES = 0x00000013
|
||||
CKK_DES2 = 0x00000014
|
||||
CKK_DES3 = 0x00000015
|
||||
CKK_CAST = 0x00000016
|
||||
CKK_CAST3 = 0x00000017
|
||||
CKK_CAST5 = 0x00000018 // Deprecated
|
||||
CKK_CAST128 = 0x00000018
|
||||
CKK_RC5 = 0x00000019
|
||||
CKK_IDEA = 0x0000001A
|
||||
CKK_SKIPJACK = 0x0000001B
|
||||
CKK_BATON = 0x0000001C
|
||||
CKK_JUNIPER = 0x0000001D
|
||||
CKK_CDMF = 0x0000001E
|
||||
CKK_AES = 0x0000001F
|
||||
CKK_BLOWFISH = 0x00000020
|
||||
CKK_TWOFISH = 0x00000021
|
||||
CKK_SECURID = 0x00000022
|
||||
CKK_HOTP = 0x00000023
|
||||
CKK_ACTI = 0x00000024
|
||||
CKK_CAMELLIA = 0x00000025
|
||||
CKK_ARIA = 0x00000026
|
||||
CKK_MD5_HMAC = 0x00000027
|
||||
CKK_SHA_1_HMAC = 0x00000028
|
||||
CKK_RIPEMD128_HMAC = 0x00000029
|
||||
CKK_RIPEMD160_HMAC = 0x0000002A
|
||||
CKK_SHA256_HMAC = 0x0000002B
|
||||
CKK_SHA384_HMAC = 0x0000002C
|
||||
CKK_SHA512_HMAC = 0x0000002D
|
||||
CKK_SHA224_HMAC = 0x0000002E
|
||||
CKK_SEED = 0x0000002F
|
||||
CKK_GOSTR3410 = 0x00000030
|
||||
CKK_GOSTR3411 = 0x00000031
|
||||
CKK_GOST28147 = 0x00000032
|
||||
CKK_SHA3_224_HMAC = 0x00000033
|
||||
CKK_SHA3_256_HMAC = 0x00000034
|
||||
CKK_SHA3_384_HMAC = 0x00000035
|
||||
CKK_SHA3_512_HMAC = 0x00000036
|
||||
CKK_VENDOR_DEFINED = 0x80000000
|
||||
CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0
|
||||
CK_CERTIFICATE_CATEGORY_TOKEN_USER = 1
|
||||
CK_CERTIFICATE_CATEGORY_AUTHORITY = 2
|
||||
CK_CERTIFICATE_CATEGORY_OTHER_ENTITY = 3
|
||||
CK_SECURITY_DOMAIN_UNSPECIFIED = 0
|
||||
CK_SECURITY_DOMAIN_MANUFACTURER = 1
|
||||
CK_SECURITY_DOMAIN_OPERATOR = 2
|
||||
CK_SECURITY_DOMAIN_THIRD_PARTY = 3
|
||||
CKC_X_509 = 0x00000000
|
||||
CKC_X_509_ATTR_CERT = 0x00000001
|
||||
CKC_WTLS = 0x00000002
|
||||
CKC_VENDOR_DEFINED = 0x80000000
|
||||
CKF_ARRAY_ATTRIBUTE = 0x40000000
|
||||
CK_OTP_FORMAT_DECIMAL = 0
|
||||
CK_OTP_FORMAT_HEXADECIMAL = 1
|
||||
CK_OTP_FORMAT_ALPHANUMERIC = 2
|
||||
CK_OTP_FORMAT_BINARY = 3
|
||||
CK_OTP_PARAM_IGNORED = 0
|
||||
CK_OTP_PARAM_OPTIONAL = 1
|
||||
CK_OTP_PARAM_MANDATORY = 2
|
||||
CKA_CLASS = 0x00000000
|
||||
CKA_TOKEN = 0x00000001
|
||||
CKA_PRIVATE = 0x00000002
|
||||
CKA_LABEL = 0x00000003
|
||||
CKA_APPLICATION = 0x00000010
|
||||
CKA_VALUE = 0x00000011
|
||||
CKA_OBJECT_ID = 0x00000012
|
||||
CKA_CERTIFICATE_TYPE = 0x00000080
|
||||
CKA_ISSUER = 0x00000081
|
||||
CKA_SERIAL_NUMBER = 0x00000082
|
||||
CKA_AC_ISSUER = 0x00000083
|
||||
CKA_OWNER = 0x00000084
|
||||
CKA_ATTR_TYPES = 0x00000085
|
||||
CKA_TRUSTED = 0x00000086
|
||||
CKA_CERTIFICATE_CATEGORY = 0x00000087
|
||||
CKA_JAVA_MIDP_SECURITY_DOMAIN = 0x00000088
|
||||
CKA_URL = 0x00000089
|
||||
CKA_HASH_OF_SUBJECT_PUBLIC_KEY = 0x0000008A
|
||||
CKA_HASH_OF_ISSUER_PUBLIC_KEY = 0x0000008B
|
||||
CKA_NAME_HASH_ALGORITHM = 0x0000008C
|
||||
CKA_CHECK_VALUE = 0x00000090
|
||||
CKA_KEY_TYPE = 0x00000100
|
||||
CKA_SUBJECT = 0x00000101
|
||||
CKA_ID = 0x00000102
|
||||
CKA_SENSITIVE = 0x00000103
|
||||
CKA_ENCRYPT = 0x00000104
|
||||
CKA_DECRYPT = 0x00000105
|
||||
CKA_WRAP = 0x00000106
|
||||
CKA_UNWRAP = 0x00000107
|
||||
CKA_SIGN = 0x00000108
|
||||
CKA_SIGN_RECOVER = 0x00000109
|
||||
CKA_VERIFY = 0x0000010A
|
||||
CKA_VERIFY_RECOVER = 0x0000010B
|
||||
CKA_DERIVE = 0x0000010C
|
||||
CKA_START_DATE = 0x00000110
|
||||
CKA_END_DATE = 0x00000111
|
||||
CKA_MODULUS = 0x00000120
|
||||
CKA_MODULUS_BITS = 0x00000121
|
||||
CKA_PUBLIC_EXPONENT = 0x00000122
|
||||
CKA_PRIVATE_EXPONENT = 0x00000123
|
||||
CKA_PRIME_1 = 0x00000124
|
||||
CKA_PRIME_2 = 0x00000125
|
||||
CKA_EXPONENT_1 = 0x00000126
|
||||
CKA_EXPONENT_2 = 0x00000127
|
||||
CKA_COEFFICIENT = 0x00000128
|
||||
CKA_PUBLIC_KEY_INFO = 0x00000129
|
||||
CKA_PRIME = 0x00000130
|
||||
CKA_SUBPRIME = 0x00000131
|
||||
CKA_BASE = 0x00000132
|
||||
CKA_PRIME_BITS = 0x00000133
|
||||
CKA_SUBPRIME_BITS = 0x00000134
|
||||
CKA_SUB_PRIME_BITS = CKA_SUBPRIME_BITS
|
||||
CKA_VALUE_BITS = 0x00000160
|
||||
CKA_VALUE_LEN = 0x00000161
|
||||
CKA_EXTRACTABLE = 0x00000162
|
||||
CKA_LOCAL = 0x00000163
|
||||
CKA_NEVER_EXTRACTABLE = 0x00000164
|
||||
CKA_ALWAYS_SENSITIVE = 0x00000165
|
||||
CKA_KEY_GEN_MECHANISM = 0x00000166
|
||||
CKA_MODIFIABLE = 0x00000170
|
||||
CKA_COPYABLE = 0x00000171
|
||||
CKA_DESTROYABLE = 0x00000172
|
||||
CKA_ECDSA_PARAMS = 0x00000180 // Deprecated
|
||||
CKA_EC_PARAMS = 0x00000180
|
||||
CKA_EC_POINT = 0x00000181
|
||||
CKA_SECONDARY_AUTH = 0x00000200 // Deprecated
|
||||
CKA_AUTH_PIN_FLAGS = 0x00000201 // Deprecated
|
||||
CKA_ALWAYS_AUTHENTICATE = 0x00000202
|
||||
CKA_WRAP_WITH_TRUSTED = 0x00000210
|
||||
CKA_WRAP_TEMPLATE = (CKF_ARRAY_ATTRIBUTE | 0x00000211)
|
||||
CKA_UNWRAP_TEMPLATE = (CKF_ARRAY_ATTRIBUTE | 0x00000212)
|
||||
CKA_DERIVE_TEMPLATE = (CKF_ARRAY_ATTRIBUTE | 0x00000213)
|
||||
CKA_OTP_FORMAT = 0x00000220
|
||||
CKA_OTP_LENGTH = 0x00000221
|
||||
CKA_OTP_TIME_INTERVAL = 0x00000222
|
||||
CKA_OTP_USER_FRIENDLY_MODE = 0x00000223
|
||||
CKA_OTP_CHALLENGE_REQUIREMENT = 0x00000224
|
||||
CKA_OTP_TIME_REQUIREMENT = 0x00000225
|
||||
CKA_OTP_COUNTER_REQUIREMENT = 0x00000226
|
||||
CKA_OTP_PIN_REQUIREMENT = 0x00000227
|
||||
CKA_OTP_COUNTER = 0x0000022E
|
||||
CKA_OTP_TIME = 0x0000022F
|
||||
CKA_OTP_USER_IDENTIFIER = 0x0000022A
|
||||
CKA_OTP_SERVICE_IDENTIFIER = 0x0000022B
|
||||
CKA_OTP_SERVICE_LOGO = 0x0000022C
|
||||
CKA_OTP_SERVICE_LOGO_TYPE = 0x0000022D
|
||||
CKA_GOSTR3410_PARAMS = 0x00000250
|
||||
CKA_GOSTR3411_PARAMS = 0x00000251
|
||||
CKA_GOST28147_PARAMS = 0x00000252
|
||||
CKA_HW_FEATURE_TYPE = 0x00000300
|
||||
CKA_RESET_ON_INIT = 0x00000301
|
||||
CKA_HAS_RESET = 0x00000302
|
||||
CKA_PIXEL_X = 0x00000400
|
||||
CKA_PIXEL_Y = 0x00000401
|
||||
CKA_RESOLUTION = 0x00000402
|
||||
CKA_CHAR_ROWS = 0x00000403
|
||||
CKA_CHAR_COLUMNS = 0x00000404
|
||||
CKA_COLOR = 0x00000405
|
||||
CKA_BITS_PER_PIXEL = 0x00000406
|
||||
CKA_CHAR_SETS = 0x00000480
|
||||
CKA_ENCODING_METHODS = 0x00000481
|
||||
CKA_MIME_TYPES = 0x00000482
|
||||
CKA_MECHANISM_TYPE = 0x00000500
|
||||
CKA_REQUIRED_CMS_ATTRIBUTES = 0x00000501
|
||||
CKA_DEFAULT_CMS_ATTRIBUTES = 0x00000502
|
||||
CKA_SUPPORTED_CMS_ATTRIBUTES = 0x00000503
|
||||
CKA_ALLOWED_MECHANISMS = (CKF_ARRAY_ATTRIBUTE | 0x00000600)
|
||||
CKA_VENDOR_DEFINED = 0x80000000
|
||||
CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000000
|
||||
CKM_RSA_PKCS = 0x00000001
|
||||
CKM_RSA_9796 = 0x00000002
|
||||
CKM_RSA_X_509 = 0x00000003
|
||||
CKM_MD2_RSA_PKCS = 0x00000004
|
||||
CKM_MD5_RSA_PKCS = 0x00000005
|
||||
CKM_SHA1_RSA_PKCS = 0x00000006
|
||||
CKM_RIPEMD128_RSA_PKCS = 0x00000007
|
||||
CKM_RIPEMD160_RSA_PKCS = 0x00000008
|
||||
CKM_RSA_PKCS_OAEP = 0x00000009
|
||||
CKM_RSA_X9_31_KEY_PAIR_GEN = 0x0000000A
|
||||
CKM_RSA_X9_31 = 0x0000000B
|
||||
CKM_SHA1_RSA_X9_31 = 0x0000000C
|
||||
CKM_RSA_PKCS_PSS = 0x0000000D
|
||||
CKM_SHA1_RSA_PKCS_PSS = 0x0000000E
|
||||
CKM_DSA_KEY_PAIR_GEN = 0x00000010
|
||||
CKM_DSA = 0x00000011
|
||||
CKM_DSA_SHA1 = 0x00000012
|
||||
CKM_DSA_SHA224 = 0x00000013
|
||||
CKM_DSA_SHA256 = 0x00000014
|
||||
CKM_DSA_SHA384 = 0x00000015
|
||||
CKM_DSA_SHA512 = 0x00000016
|
||||
CKM_DSA_SHA3_224 = 0x00000018
|
||||
CKM_DSA_SHA3_256 = 0x00000019
|
||||
CKM_DSA_SHA3_384 = 0x0000001A
|
||||
CKM_DSA_SHA3_512 = 0x0000001B
|
||||
CKM_DH_PKCS_KEY_PAIR_GEN = 0x00000020
|
||||
CKM_DH_PKCS_DERIVE = 0x00000021
|
||||
CKM_X9_42_DH_KEY_PAIR_GEN = 0x00000030
|
||||
CKM_X9_42_DH_DERIVE = 0x00000031
|
||||
CKM_X9_42_DH_HYBRID_DERIVE = 0x00000032
|
||||
CKM_X9_42_MQV_DERIVE = 0x00000033
|
||||
CKM_SHA256_RSA_PKCS = 0x00000040
|
||||
CKM_SHA384_RSA_PKCS = 0x00000041
|
||||
CKM_SHA512_RSA_PKCS = 0x00000042
|
||||
CKM_SHA256_RSA_PKCS_PSS = 0x00000043
|
||||
CKM_SHA384_RSA_PKCS_PSS = 0x00000044
|
||||
CKM_SHA512_RSA_PKCS_PSS = 0x00000045
|
||||
CKM_SHA224_RSA_PKCS = 0x00000046
|
||||
CKM_SHA224_RSA_PKCS_PSS = 0x00000047
|
||||
CKM_SHA512_224 = 0x00000048
|
||||
CKM_SHA512_224_HMAC = 0x00000049
|
||||
CKM_SHA512_224_HMAC_GENERAL = 0x0000004A
|
||||
CKM_SHA512_224_KEY_DERIVATION = 0x0000004B
|
||||
CKM_SHA512_256 = 0x0000004C
|
||||
CKM_SHA512_256_HMAC = 0x0000004D
|
||||
CKM_SHA512_256_HMAC_GENERAL = 0x0000004E
|
||||
CKM_SHA512_256_KEY_DERIVATION = 0x0000004F
|
||||
CKM_SHA512_T = 0x00000050
|
||||
CKM_SHA512_T_HMAC = 0x00000051
|
||||
CKM_SHA512_T_HMAC_GENERAL = 0x00000052
|
||||
CKM_SHA512_T_KEY_DERIVATION = 0x00000053
|
||||
CKM_SHA3_256_RSA_PKCS = 0x00000060
|
||||
CKM_SHA3_384_RSA_PKCS = 0x00000061
|
||||
CKM_SHA3_512_RSA_PKCS = 0x00000062
|
||||
CKM_SHA3_256_RSA_PKCS_PSS = 0x00000063
|
||||
CKM_SHA3_384_RSA_PKCS_PSS = 0x00000064
|
||||
CKM_SHA3_512_RSA_PKCS_PSS = 0x00000065
|
||||
CKM_SHA3_224_RSA_PKCS = 0x00000066
|
||||
CKM_SHA3_224_RSA_PKCS_PSS = 0x00000067
|
||||
CKM_RC2_KEY_GEN = 0x00000100
|
||||
CKM_RC2_ECB = 0x00000101
|
||||
CKM_RC2_CBC = 0x00000102
|
||||
CKM_RC2_MAC = 0x00000103
|
||||
CKM_RC2_MAC_GENERAL = 0x00000104
|
||||
CKM_RC2_CBC_PAD = 0x00000105
|
||||
CKM_RC4_KEY_GEN = 0x00000110
|
||||
CKM_RC4 = 0x00000111
|
||||
CKM_DES_KEY_GEN = 0x00000120
|
||||
CKM_DES_ECB = 0x00000121
|
||||
CKM_DES_CBC = 0x00000122
|
||||
CKM_DES_MAC = 0x00000123
|
||||
CKM_DES_MAC_GENERAL = 0x00000124
|
||||
CKM_DES_CBC_PAD = 0x00000125
|
||||
CKM_DES2_KEY_GEN = 0x00000130
|
||||
CKM_DES3_KEY_GEN = 0x00000131
|
||||
CKM_DES3_ECB = 0x00000132
|
||||
CKM_DES3_CBC = 0x00000133
|
||||
CKM_DES3_MAC = 0x00000134
|
||||
CKM_DES3_MAC_GENERAL = 0x00000135
|
||||
CKM_DES3_CBC_PAD = 0x00000136
|
||||
CKM_DES3_CMAC_GENERAL = 0x00000137
|
||||
CKM_DES3_CMAC = 0x00000138
|
||||
CKM_CDMF_KEY_GEN = 0x00000140
|
||||
CKM_CDMF_ECB = 0x00000141
|
||||
CKM_CDMF_CBC = 0x00000142
|
||||
CKM_CDMF_MAC = 0x00000143
|
||||
CKM_CDMF_MAC_GENERAL = 0x00000144
|
||||
CKM_CDMF_CBC_PAD = 0x00000145
|
||||
CKM_DES_OFB64 = 0x00000150
|
||||
CKM_DES_OFB8 = 0x00000151
|
||||
CKM_DES_CFB64 = 0x00000152
|
||||
CKM_DES_CFB8 = 0x00000153
|
||||
CKM_MD2 = 0x00000200
|
||||
CKM_MD2_HMAC = 0x00000201
|
||||
CKM_MD2_HMAC_GENERAL = 0x00000202
|
||||
CKM_MD5 = 0x00000210
|
||||
CKM_MD5_HMAC = 0x00000211
|
||||
CKM_MD5_HMAC_GENERAL = 0x00000212
|
||||
CKM_SHA_1 = 0x00000220
|
||||
CKM_SHA_1_HMAC = 0x00000221
|
||||
CKM_SHA_1_HMAC_GENERAL = 0x00000222
|
||||
CKM_RIPEMD128 = 0x00000230
|
||||
CKM_RIPEMD128_HMAC = 0x00000231
|
||||
CKM_RIPEMD128_HMAC_GENERAL = 0x00000232
|
||||
CKM_RIPEMD160 = 0x00000240
|
||||
CKM_RIPEMD160_HMAC = 0x00000241
|
||||
CKM_RIPEMD160_HMAC_GENERAL = 0x00000242
|
||||
CKM_SHA256 = 0x00000250
|
||||
CKM_SHA256_HMAC = 0x00000251
|
||||
CKM_SHA256_HMAC_GENERAL = 0x00000252
|
||||
CKM_SHA224 = 0x00000255
|
||||
CKM_SHA224_HMAC = 0x00000256
|
||||
CKM_SHA224_HMAC_GENERAL = 0x00000257
|
||||
CKM_SHA384 = 0x00000260
|
||||
CKM_SHA384_HMAC = 0x00000261
|
||||
CKM_SHA384_HMAC_GENERAL = 0x00000262
|
||||
CKM_SHA512 = 0x00000270
|
||||
CKM_SHA512_HMAC = 0x00000271
|
||||
CKM_SHA512_HMAC_GENERAL = 0x00000272
|
||||
CKM_SECURID_KEY_GEN = 0x00000280
|
||||
CKM_SECURID = 0x00000282
|
||||
CKM_HOTP_KEY_GEN = 0x00000290
|
||||
CKM_HOTP = 0x00000291
|
||||
CKM_ACTI = 0x000002A0
|
||||
CKM_ACTI_KEY_GEN = 0x000002A1
|
||||
CKM_SHA3_256 = 0x000002B0
|
||||
CKM_SHA3_256_HMAC = 0x000002B1
|
||||
CKM_SHA3_256_HMAC_GENERAL = 0x000002B2
|
||||
CKM_SHA3_256_KEY_GEN = 0x000002B3
|
||||
CKM_SHA3_224 = 0x000002B5
|
||||
CKM_SHA3_224_HMAC = 0x000002B6
|
||||
CKM_SHA3_224_HMAC_GENERAL = 0x000002B7
|
||||
CKM_SHA3_224_KEY_GEN = 0x000002B8
|
||||
CKM_SHA3_384 = 0x000002C0
|
||||
CKM_SHA3_384_HMAC = 0x000002C1
|
||||
CKM_SHA3_384_HMAC_GENERAL = 0x000002C2
|
||||
CKM_SHA3_384_KEY_GEN = 0x000002C3
|
||||
CKM_SHA3_512 = 0x000002D0
|
||||
CKM_SHA3_512_HMAC = 0x000002D1
|
||||
CKM_SHA3_512_HMAC_GENERAL = 0x000002D2
|
||||
CKM_SHA3_512_KEY_GEN = 0x000002D3
|
||||
CKM_CAST_KEY_GEN = 0x00000300
|
||||
CKM_CAST_ECB = 0x00000301
|
||||
CKM_CAST_CBC = 0x00000302
|
||||
CKM_CAST_MAC = 0x00000303
|
||||
CKM_CAST_MAC_GENERAL = 0x00000304
|
||||
CKM_CAST_CBC_PAD = 0x00000305
|
||||
CKM_CAST3_KEY_GEN = 0x00000310
|
||||
CKM_CAST3_ECB = 0x00000311
|
||||
CKM_CAST3_CBC = 0x00000312
|
||||
CKM_CAST3_MAC = 0x00000313
|
||||
CKM_CAST3_MAC_GENERAL = 0x00000314
|
||||
CKM_CAST3_CBC_PAD = 0x00000315
|
||||
CKM_CAST5_KEY_GEN = 0x00000320
|
||||
CKM_CAST128_KEY_GEN = 0x00000320
|
||||
CKM_CAST5_ECB = 0x00000321
|
||||
CKM_CAST128_ECB = 0x00000321
|
||||
CKM_CAST5_CBC = 0x00000322 // Deprecated
|
||||
CKM_CAST128_CBC = 0x00000322
|
||||
CKM_CAST5_MAC = 0x00000323 // Deprecated
|
||||
CKM_CAST128_MAC = 0x00000323
|
||||
CKM_CAST5_MAC_GENERAL = 0x00000324 // Deprecated
|
||||
CKM_CAST128_MAC_GENERAL = 0x00000324
|
||||
CKM_CAST5_CBC_PAD = 0x00000325 // Deprecated
|
||||
CKM_CAST128_CBC_PAD = 0x00000325
|
||||
CKM_RC5_KEY_GEN = 0x00000330
|
||||
CKM_RC5_ECB = 0x00000331
|
||||
CKM_RC5_CBC = 0x00000332
|
||||
CKM_RC5_MAC = 0x00000333
|
||||
CKM_RC5_MAC_GENERAL = 0x00000334
|
||||
CKM_RC5_CBC_PAD = 0x00000335
|
||||
CKM_IDEA_KEY_GEN = 0x00000340
|
||||
CKM_IDEA_ECB = 0x00000341
|
||||
CKM_IDEA_CBC = 0x00000342
|
||||
CKM_IDEA_MAC = 0x00000343
|
||||
CKM_IDEA_MAC_GENERAL = 0x00000344
|
||||
CKM_IDEA_CBC_PAD = 0x00000345
|
||||
CKM_GENERIC_SECRET_KEY_GEN = 0x00000350
|
||||
CKM_CONCATENATE_BASE_AND_KEY = 0x00000360
|
||||
CKM_CONCATENATE_BASE_AND_DATA = 0x00000362
|
||||
CKM_CONCATENATE_DATA_AND_BASE = 0x00000363
|
||||
CKM_XOR_BASE_AND_DATA = 0x00000364
|
||||
CKM_EXTRACT_KEY_FROM_KEY = 0x00000365
|
||||
CKM_SSL3_PRE_MASTER_KEY_GEN = 0x00000370
|
||||
CKM_SSL3_MASTER_KEY_DERIVE = 0x00000371
|
||||
CKM_SSL3_KEY_AND_MAC_DERIVE = 0x00000372
|
||||
CKM_SSL3_MASTER_KEY_DERIVE_DH = 0x00000373
|
||||
CKM_TLS_PRE_MASTER_KEY_GEN = 0x00000374
|
||||
CKM_TLS_MASTER_KEY_DERIVE = 0x00000375
|
||||
CKM_TLS_KEY_AND_MAC_DERIVE = 0x00000376
|
||||
CKM_TLS_MASTER_KEY_DERIVE_DH = 0x00000377
|
||||
CKM_TLS_PRF = 0x00000378
|
||||
CKM_SSL3_MD5_MAC = 0x00000380
|
||||
CKM_SSL3_SHA1_MAC = 0x00000381
|
||||
CKM_MD5_KEY_DERIVATION = 0x00000390
|
||||
CKM_MD2_KEY_DERIVATION = 0x00000391
|
||||
CKM_SHA1_KEY_DERIVATION = 0x00000392
|
||||
CKM_SHA256_KEY_DERIVATION = 0x00000393
|
||||
CKM_SHA384_KEY_DERIVATION = 0x00000394
|
||||
CKM_SHA512_KEY_DERIVATION = 0x00000395
|
||||
CKM_SHA224_KEY_DERIVATION = 0x00000396
|
||||
CKM_SHA3_256_KEY_DERIVE = 0x00000397
|
||||
CKM_SHA3_224_KEY_DERIVE = 0x00000398
|
||||
CKM_SHA3_384_KEY_DERIVE = 0x00000399
|
||||
CKM_SHA3_512_KEY_DERIVE = 0x0000039A
|
||||
CKM_SHAKE_128_KEY_DERIVE = 0x0000039B
|
||||
CKM_SHAKE_256_KEY_DERIVE = 0x0000039C
|
||||
CKM_PBE_MD2_DES_CBC = 0x000003A0
|
||||
CKM_PBE_MD5_DES_CBC = 0x000003A1
|
||||
CKM_PBE_MD5_CAST_CBC = 0x000003A2
|
||||
CKM_PBE_MD5_CAST3_CBC = 0x000003A3
|
||||
CKM_PBE_MD5_CAST5_CBC = 0x000003A4 // Deprecated
|
||||
CKM_PBE_MD5_CAST128_CBC = 0x000003A4
|
||||
CKM_PBE_SHA1_CAST5_CBC = 0x000003A5 // Deprecated
|
||||
CKM_PBE_SHA1_CAST128_CBC = 0x000003A5
|
||||
CKM_PBE_SHA1_RC4_128 = 0x000003A6
|
||||
CKM_PBE_SHA1_RC4_40 = 0x000003A7
|
||||
CKM_PBE_SHA1_DES3_EDE_CBC = 0x000003A8
|
||||
CKM_PBE_SHA1_DES2_EDE_CBC = 0x000003A9
|
||||
CKM_PBE_SHA1_RC2_128_CBC = 0x000003AA
|
||||
CKM_PBE_SHA1_RC2_40_CBC = 0x000003AB
|
||||
CKM_PKCS5_PBKD2 = 0x000003B0
|
||||
CKM_PBA_SHA1_WITH_SHA1_HMAC = 0x000003C0
|
||||
CKM_WTLS_PRE_MASTER_KEY_GEN = 0x000003D0
|
||||
CKM_WTLS_MASTER_KEY_DERIVE = 0x000003D1
|
||||
CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC = 0x000003D2
|
||||
CKM_WTLS_PRF = 0x000003D3
|
||||
CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE = 0x000003D4
|
||||
CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE = 0x000003D5
|
||||
CKM_TLS10_MAC_SERVER = 0x000003D6
|
||||
CKM_TLS10_MAC_CLIENT = 0x000003D7
|
||||
CKM_TLS12_MAC = 0x000003D8
|
||||
CKM_TLS12_KDF = 0x000003D9
|
||||
CKM_TLS12_MASTER_KEY_DERIVE = 0x000003E0
|
||||
CKM_TLS12_KEY_AND_MAC_DERIVE = 0x000003E1
|
||||
CKM_TLS12_MASTER_KEY_DERIVE_DH = 0x000003E2
|
||||
CKM_TLS12_KEY_SAFE_DERIVE = 0x000003E3
|
||||
CKM_TLS_MAC = 0x000003E4
|
||||
CKM_TLS_KDF = 0x000003E5
|
||||
CKM_KEY_WRAP_LYNKS = 0x00000400
|
||||
CKM_KEY_WRAP_SET_OAEP = 0x00000401
|
||||
CKM_CMS_SIG = 0x00000500
|
||||
CKM_KIP_DERIVE = 0x00000510
|
||||
CKM_KIP_WRAP = 0x00000511
|
||||
CKM_KIP_MAC = 0x00000512
|
||||
CKM_CAMELLIA_KEY_GEN = 0x00000550
|
||||
CKM_CAMELLIA_ECB = 0x00000551
|
||||
CKM_CAMELLIA_CBC = 0x00000552
|
||||
CKM_CAMELLIA_MAC = 0x00000553
|
||||
CKM_CAMELLIA_MAC_GENERAL = 0x00000554
|
||||
CKM_CAMELLIA_CBC_PAD = 0x00000555
|
||||
CKM_CAMELLIA_ECB_ENCRYPT_DATA = 0x00000556
|
||||
CKM_CAMELLIA_CBC_ENCRYPT_DATA = 0x00000557
|
||||
CKM_CAMELLIA_CTR = 0x00000558
|
||||
CKM_ARIA_KEY_GEN = 0x00000560
|
||||
CKM_ARIA_ECB = 0x00000561
|
||||
CKM_ARIA_CBC = 0x00000562
|
||||
CKM_ARIA_MAC = 0x00000563
|
||||
CKM_ARIA_MAC_GENERAL = 0x00000564
|
||||
CKM_ARIA_CBC_PAD = 0x00000565
|
||||
CKM_ARIA_ECB_ENCRYPT_DATA = 0x00000566
|
||||
CKM_ARIA_CBC_ENCRYPT_DATA = 0x00000567
|
||||
CKM_SEED_KEY_GEN = 0x00000650
|
||||
CKM_SEED_ECB = 0x00000651
|
||||
CKM_SEED_CBC = 0x00000652
|
||||
CKM_SEED_MAC = 0x00000653
|
||||
CKM_SEED_MAC_GENERAL = 0x00000654
|
||||
CKM_SEED_CBC_PAD = 0x00000655
|
||||
CKM_SEED_ECB_ENCRYPT_DATA = 0x00000656
|
||||
CKM_SEED_CBC_ENCRYPT_DATA = 0x00000657
|
||||
CKM_SKIPJACK_KEY_GEN = 0x00001000
|
||||
CKM_SKIPJACK_ECB64 = 0x00001001
|
||||
CKM_SKIPJACK_CBC64 = 0x00001002
|
||||
CKM_SKIPJACK_OFB64 = 0x00001003
|
||||
CKM_SKIPJACK_CFB64 = 0x00001004
|
||||
CKM_SKIPJACK_CFB32 = 0x00001005
|
||||
CKM_SKIPJACK_CFB16 = 0x00001006
|
||||
CKM_SKIPJACK_CFB8 = 0x00001007
|
||||
CKM_SKIPJACK_WRAP = 0x00001008
|
||||
CKM_SKIPJACK_PRIVATE_WRAP = 0x00001009
|
||||
CKM_SKIPJACK_RELAYX = 0x0000100a
|
||||
CKM_KEA_KEY_PAIR_GEN = 0x00001010
|
||||
CKM_KEA_KEY_DERIVE = 0x00001011
|
||||
CKM_KEA_DERIVE = 0x00001012
|
||||
CKM_FORTEZZA_TIMESTAMP = 0x00001020
|
||||
CKM_BATON_KEY_GEN = 0x00001030
|
||||
CKM_BATON_ECB128 = 0x00001031
|
||||
CKM_BATON_ECB96 = 0x00001032
|
||||
CKM_BATON_CBC128 = 0x00001033
|
||||
CKM_BATON_COUNTER = 0x00001034
|
||||
CKM_BATON_SHUFFLE = 0x00001035
|
||||
CKM_BATON_WRAP = 0x00001036
|
||||
CKM_ECDSA_KEY_PAIR_GEN = 0x00001040 // Deprecated
|
||||
CKM_EC_KEY_PAIR_GEN = 0x00001040
|
||||
CKM_ECDSA = 0x00001041
|
||||
CKM_ECDSA_SHA1 = 0x00001042
|
||||
CKM_ECDSA_SHA224 = 0x00001043
|
||||
CKM_ECDSA_SHA256 = 0x00001044
|
||||
CKM_ECDSA_SHA384 = 0x00001045
|
||||
CKM_ECDSA_SHA512 = 0x00001046
|
||||
CKM_ECDH1_DERIVE = 0x00001050
|
||||
CKM_ECDH1_COFACTOR_DERIVE = 0x00001051
|
||||
CKM_ECMQV_DERIVE = 0x00001052
|
||||
CKM_ECDH_AES_KEY_WRAP = 0x00001053
|
||||
CKM_RSA_AES_KEY_WRAP = 0x00001054
|
||||
CKM_JUNIPER_KEY_GEN = 0x00001060
|
||||
CKM_JUNIPER_ECB128 = 0x00001061
|
||||
CKM_JUNIPER_CBC128 = 0x00001062
|
||||
CKM_JUNIPER_COUNTER = 0x00001063
|
||||
CKM_JUNIPER_SHUFFLE = 0x00001064
|
||||
CKM_JUNIPER_WRAP = 0x00001065
|
||||
CKM_FASTHASH = 0x00001070
|
||||
CKM_AES_KEY_GEN = 0x00001080
|
||||
CKM_AES_ECB = 0x00001081
|
||||
CKM_AES_CBC = 0x00001082
|
||||
CKM_AES_MAC = 0x00001083
|
||||
CKM_AES_MAC_GENERAL = 0x00001084
|
||||
CKM_AES_CBC_PAD = 0x00001085
|
||||
CKM_AES_CTR = 0x00001086
|
||||
CKM_AES_GCM = 0x00001087
|
||||
CKM_AES_CCM = 0x00001088
|
||||
CKM_AES_CTS = 0x00001089
|
||||
CKM_AES_CMAC = 0x0000108A
|
||||
CKM_AES_CMAC_GENERAL = 0x0000108B
|
||||
CKM_AES_XCBC_MAC = 0x0000108C
|
||||
CKM_AES_XCBC_MAC_96 = 0x0000108D
|
||||
CKM_AES_GMAC = 0x0000108E
|
||||
CKM_BLOWFISH_KEY_GEN = 0x00001090
|
||||
CKM_BLOWFISH_CBC = 0x00001091
|
||||
CKM_TWOFISH_KEY_GEN = 0x00001092
|
||||
CKM_TWOFISH_CBC = 0x00001093
|
||||
CKM_BLOWFISH_CBC_PAD = 0x00001094
|
||||
CKM_TWOFISH_CBC_PAD = 0x00001095
|
||||
CKM_DES_ECB_ENCRYPT_DATA = 0x00001100
|
||||
CKM_DES_CBC_ENCRYPT_DATA = 0x00001101
|
||||
CKM_DES3_ECB_ENCRYPT_DATA = 0x00001102
|
||||
CKM_DES3_CBC_ENCRYPT_DATA = 0x00001103
|
||||
CKM_AES_ECB_ENCRYPT_DATA = 0x00001104
|
||||
CKM_AES_CBC_ENCRYPT_DATA = 0x00001105
|
||||
CKM_GOSTR3410_KEY_PAIR_GEN = 0x00001200
|
||||
CKM_GOSTR3410 = 0x00001201
|
||||
CKM_GOSTR3410_WITH_GOSTR3411 = 0x00001202
|
||||
CKM_GOSTR3410_KEY_WRAP = 0x00001203
|
||||
CKM_GOSTR3410_DERIVE = 0x00001204
|
||||
CKM_GOSTR3411 = 0x00001210
|
||||
CKM_GOSTR3411_HMAC = 0x00001211
|
||||
CKM_GOST28147_KEY_GEN = 0x00001220
|
||||
CKM_GOST28147_ECB = 0x00001221
|
||||
CKM_GOST28147 = 0x00001222
|
||||
CKM_GOST28147_MAC = 0x00001223
|
||||
CKM_GOST28147_KEY_WRAP = 0x00001224
|
||||
CKM_DSA_PARAMETER_GEN = 0x00002000
|
||||
CKM_DH_PKCS_PARAMETER_GEN = 0x00002001
|
||||
CKM_X9_42_DH_PARAMETER_GEN = 0x00002002
|
||||
CKM_DSA_PROBABLISTIC_PARAMETER_GEN = 0x00002003
|
||||
CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN = 0x00002004
|
||||
CKM_AES_OFB = 0x00002104
|
||||
CKM_AES_CFB64 = 0x00002105
|
||||
CKM_AES_CFB8 = 0x00002106
|
||||
CKM_AES_CFB128 = 0x00002107
|
||||
CKM_AES_CFB1 = 0x00002108
|
||||
CKM_AES_KEY_WRAP = 0x00002109
|
||||
CKM_AES_KEY_WRAP_PAD = 0x0000210A
|
||||
CKM_RSA_PKCS_TPM_1_1 = 0x00004001
|
||||
CKM_RSA_PKCS_OAEP_TPM_1_1 = 0x00004002
|
||||
CKM_VENDOR_DEFINED = 0x80000000
|
||||
CKF_HW = 0x00000001
|
||||
CKF_ENCRYPT = 0x00000100
|
||||
CKF_DECRYPT = 0x00000200
|
||||
CKF_DIGEST = 0x00000400
|
||||
CKF_SIGN = 0x00000800
|
||||
CKF_SIGN_RECOVER = 0x00001000
|
||||
CKF_VERIFY = 0x00002000
|
||||
CKF_VERIFY_RECOVER = 0x00004000
|
||||
CKF_GENERATE = 0x00008000
|
||||
CKF_GENERATE_KEY_PAIR = 0x00010000
|
||||
CKF_WRAP = 0x00020000
|
||||
CKF_UNWRAP = 0x00040000
|
||||
CKF_DERIVE = 0x00080000
|
||||
CKF_EC_F_P = 0x00100000
|
||||
CKF_EC_F_2M = 0x00200000
|
||||
CKF_EC_ECPARAMETERS = 0x00400000
|
||||
CKF_EC_NAMEDCURVE = 0x00800000
|
||||
CKF_EC_UNCOMPRESS = 0x01000000
|
||||
CKF_EC_COMPRESS = 0x02000000
|
||||
CKF_EXTENSION = 0x80000000
|
||||
CKR_OK = 0x00000000
|
||||
CKR_CANCEL = 0x00000001
|
||||
CKR_HOST_MEMORY = 0x00000002
|
||||
CKR_SLOT_ID_INVALID = 0x00000003
|
||||
CKR_GENERAL_ERROR = 0x00000005
|
||||
CKR_FUNCTION_FAILED = 0x00000006
|
||||
CKR_ARGUMENTS_BAD = 0x00000007
|
||||
CKR_NO_EVENT = 0x00000008
|
||||
CKR_NEED_TO_CREATE_THREADS = 0x00000009
|
||||
CKR_CANT_LOCK = 0x0000000A
|
||||
CKR_ATTRIBUTE_READ_ONLY = 0x00000010
|
||||
CKR_ATTRIBUTE_SENSITIVE = 0x00000011
|
||||
CKR_ATTRIBUTE_TYPE_INVALID = 0x00000012
|
||||
CKR_ATTRIBUTE_VALUE_INVALID = 0x00000013
|
||||
CKR_ACTION_PROHIBITED = 0x0000001B
|
||||
CKR_DATA_INVALID = 0x00000020
|
||||
CKR_DATA_LEN_RANGE = 0x00000021
|
||||
CKR_DEVICE_ERROR = 0x00000030
|
||||
CKR_DEVICE_MEMORY = 0x00000031
|
||||
CKR_DEVICE_REMOVED = 0x00000032
|
||||
CKR_ENCRYPTED_DATA_INVALID = 0x00000040
|
||||
CKR_ENCRYPTED_DATA_LEN_RANGE = 0x00000041
|
||||
CKR_FUNCTION_CANCELED = 0x00000050
|
||||
CKR_FUNCTION_NOT_PARALLEL = 0x00000051
|
||||
CKR_FUNCTION_NOT_SUPPORTED = 0x00000054
|
||||
CKR_KEY_HANDLE_INVALID = 0x00000060
|
||||
CKR_KEY_SIZE_RANGE = 0x00000062
|
||||
CKR_KEY_TYPE_INCONSISTENT = 0x00000063
|
||||
CKR_KEY_NOT_NEEDED = 0x00000064
|
||||
CKR_KEY_CHANGED = 0x00000065
|
||||
CKR_KEY_NEEDED = 0x00000066
|
||||
CKR_KEY_INDIGESTIBLE = 0x00000067
|
||||
CKR_KEY_FUNCTION_NOT_PERMITTED = 0x00000068
|
||||
CKR_KEY_NOT_WRAPPABLE = 0x00000069
|
||||
CKR_KEY_UNEXTRACTABLE = 0x0000006A
|
||||
CKR_MECHANISM_INVALID = 0x00000070
|
||||
CKR_MECHANISM_PARAM_INVALID = 0x00000071
|
||||
CKR_OBJECT_HANDLE_INVALID = 0x00000082
|
||||
CKR_OPERATION_ACTIVE = 0x00000090
|
||||
CKR_OPERATION_NOT_INITIALIZED = 0x00000091
|
||||
CKR_PIN_INCORRECT = 0x000000A0
|
||||
CKR_PIN_INVALID = 0x000000A1
|
||||
CKR_PIN_LEN_RANGE = 0x000000A2
|
||||
CKR_PIN_EXPIRED = 0x000000A3
|
||||
CKR_PIN_LOCKED = 0x000000A4
|
||||
CKR_SESSION_CLOSED = 0x000000B0
|
||||
CKR_SESSION_COUNT = 0x000000B1
|
||||
CKR_SESSION_HANDLE_INVALID = 0x000000B3
|
||||
CKR_SESSION_PARALLEL_NOT_SUPPORTED = 0x000000B4
|
||||
CKR_SESSION_READ_ONLY = 0x000000B5
|
||||
CKR_SESSION_EXISTS = 0x000000B6
|
||||
CKR_SESSION_READ_ONLY_EXISTS = 0x000000B7
|
||||
CKR_SESSION_READ_WRITE_SO_EXISTS = 0x000000B8
|
||||
CKR_SIGNATURE_INVALID = 0x000000C0
|
||||
CKR_SIGNATURE_LEN_RANGE = 0x000000C1
|
||||
CKR_TEMPLATE_INCOMPLETE = 0x000000D0
|
||||
CKR_TEMPLATE_INCONSISTENT = 0x000000D1
|
||||
CKR_TOKEN_NOT_PRESENT = 0x000000E0
|
||||
CKR_TOKEN_NOT_RECOGNIZED = 0x000000E1
|
||||
CKR_TOKEN_WRITE_PROTECTED = 0x000000E2
|
||||
CKR_UNWRAPPING_KEY_HANDLE_INVALID = 0x000000F0
|
||||
CKR_UNWRAPPING_KEY_SIZE_RANGE = 0x000000F1
|
||||
CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT = 0x000000F2
|
||||
CKR_USER_ALREADY_LOGGED_IN = 0x00000100
|
||||
CKR_USER_NOT_LOGGED_IN = 0x00000101
|
||||
CKR_USER_PIN_NOT_INITIALIZED = 0x00000102
|
||||
CKR_USER_TYPE_INVALID = 0x00000103
|
||||
CKR_USER_ANOTHER_ALREADY_LOGGED_IN = 0x00000104
|
||||
CKR_USER_TOO_MANY_TYPES = 0x00000105
|
||||
CKR_WRAPPED_KEY_INVALID = 0x00000110
|
||||
CKR_WRAPPED_KEY_LEN_RANGE = 0x00000112
|
||||
CKR_WRAPPING_KEY_HANDLE_INVALID = 0x00000113
|
||||
CKR_WRAPPING_KEY_SIZE_RANGE = 0x00000114
|
||||
CKR_WRAPPING_KEY_TYPE_INCONSISTENT = 0x00000115
|
||||
CKR_RANDOM_SEED_NOT_SUPPORTED = 0x00000120
|
||||
CKR_RANDOM_NO_RNG = 0x00000121
|
||||
CKR_DOMAIN_PARAMS_INVALID = 0x00000130
|
||||
CKR_CURVE_NOT_SUPPORTED = 0x00000140
|
||||
CKR_BUFFER_TOO_SMALL = 0x00000150
|
||||
CKR_SAVED_STATE_INVALID = 0x00000160
|
||||
CKR_INFORMATION_SENSITIVE = 0x00000170
|
||||
CKR_STATE_UNSAVEABLE = 0x00000180
|
||||
CKR_CRYPTOKI_NOT_INITIALIZED = 0x00000190
|
||||
CKR_CRYPTOKI_ALREADY_INITIALIZED = 0x00000191
|
||||
CKR_MUTEX_BAD = 0x000001A0
|
||||
CKR_MUTEX_NOT_LOCKED = 0x000001A1
|
||||
CKR_NEW_PIN_MODE = 0x000001B0
|
||||
CKR_NEXT_OTP = 0x000001B1
|
||||
CKR_EXCEEDED_MAX_ITERATIONS = 0x000001B5
|
||||
CKR_FIPS_SELF_TEST_FAILED = 0x000001B6
|
||||
CKR_LIBRARY_LOAD_FAILED = 0x000001B7
|
||||
CKR_PIN_TOO_WEAK = 0x000001B8
|
||||
CKR_PUBLIC_KEY_INVALID = 0x000001B9
|
||||
CKR_FUNCTION_REJECTED = 0x00000200
|
||||
CKR_VENDOR_DEFINED = 0x80000000
|
||||
CKF_LIBRARY_CANT_CREATE_OS_THREADS = 0x00000001
|
||||
CKF_OS_LOCKING_OK = 0x00000002
|
||||
CKF_DONT_BLOCK = 1
|
||||
CKG_MGF1_SHA1 = 0x00000001
|
||||
CKG_MGF1_SHA256 = 0x00000002
|
||||
CKG_MGF1_SHA384 = 0x00000003
|
||||
CKG_MGF1_SHA512 = 0x00000004
|
||||
CKG_MGF1_SHA224 = 0x00000005
|
||||
CKZ_DATA_SPECIFIED = 0x00000001
|
||||
CKD_NULL = 0x00000001
|
||||
CKD_SHA1_KDF = 0x00000002
|
||||
CKD_SHA1_KDF_ASN1 = 0x00000003
|
||||
CKD_SHA1_KDF_CONCATENATE = 0x00000004
|
||||
CKD_SHA224_KDF = 0x00000005
|
||||
CKD_SHA256_KDF = 0x00000006
|
||||
CKD_SHA384_KDF = 0x00000007
|
||||
CKD_SHA512_KDF = 0x00000008
|
||||
CKD_CPDIVERSIFY_KDF = 0x00000009
|
||||
CKD_SHA3_224_KDF = 0x0000000A
|
||||
CKD_SHA3_256_KDF = 0x0000000B
|
||||
CKD_SHA3_384_KDF = 0x0000000C
|
||||
CKD_SHA3_512_KDF = 0x0000000D
|
||||
CKP_PKCS5_PBKD2_HMAC_SHA1 = 0x00000001
|
||||
CKP_PKCS5_PBKD2_HMAC_GOSTR3411 = 0x00000002
|
||||
CKP_PKCS5_PBKD2_HMAC_SHA224 = 0x00000003
|
||||
CKP_PKCS5_PBKD2_HMAC_SHA256 = 0x00000004
|
||||
CKP_PKCS5_PBKD2_HMAC_SHA384 = 0x00000005
|
||||
CKP_PKCS5_PBKD2_HMAC_SHA512 = 0x00000006
|
||||
CKP_PKCS5_PBKD2_HMAC_SHA512_224 = 0x00000007
|
||||
CKP_PKCS5_PBKD2_HMAC_SHA512_256 = 0x00000008
|
||||
CKZ_SALT_SPECIFIED = 0x00000001
|
||||
CK_OTP_VALUE = 0
|
||||
CK_OTP_PIN = 1
|
||||
CK_OTP_CHALLENGE = 2
|
||||
CK_OTP_TIME = 3
|
||||
CK_OTP_COUNTER = 4
|
||||
CK_OTP_FLAGS = 5
|
||||
CK_OTP_OUTPUT_LENGTH = 6
|
||||
CK_OTP_OUTPUT_FORMAT = 7
|
||||
CKF_NEXT_OTP = 0x00000001
|
||||
CKF_EXCLUDE_TIME = 0x00000002
|
||||
CKF_EXCLUDE_COUNTER = 0x00000004
|
||||
CKF_EXCLUDE_CHALLENGE = 0x00000008
|
||||
CKF_EXCLUDE_PIN = 0x00000010
|
||||
CKF_USER_FRIENDLY_OTP = 0x00000020
|
||||
)
|
2
vendor/github.com/stefanberger/go-pkcs11uri/.gitignore
generated
vendored
Normal file
2
vendor/github.com/stefanberger/go-pkcs11uri/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*~
|
||||
pkcs11uri
|
25
vendor/github.com/stefanberger/go-pkcs11uri/.travis.yml
generated
vendored
Normal file
25
vendor/github.com/stefanberger/go-pkcs11uri/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
dist: bionic
|
||||
language: go
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
||||
go:
|
||||
- "1.13.x"
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- softhsm2
|
||||
|
||||
install:
|
||||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0
|
||||
|
||||
script:
|
||||
- make
|
||||
- make check
|
||||
- make test
|
177
vendor/github.com/stefanberger/go-pkcs11uri/LICENSE
generated
vendored
Normal file
177
vendor/github.com/stefanberger/go-pkcs11uri/LICENSE
generated
vendored
Normal file
@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
28
vendor/github.com/stefanberger/go-pkcs11uri/Makefile
generated
vendored
Normal file
28
vendor/github.com/stefanberger/go-pkcs11uri/Makefile
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# Copyright IBM Corporation, 2020
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
.PHONY: check build test
|
||||
|
||||
all: build
|
||||
|
||||
FORCE:
|
||||
|
||||
check:
|
||||
golangci-lint run
|
||||
|
||||
build:
|
||||
go build ./...
|
||||
|
||||
test:
|
||||
go test ./... -test.v
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user