mirror of
https://github.com/containers/podman.git
synced 2025-06-25 12:20:42 +08:00
Merge pull request #7203 from TomSweeneyRedHat/dev/tsweeney/bump_buildah
Bump to Buildah 1.16.0-dev in upstream
This commit is contained in:
3
go.mod
3
go.mod
@ -10,7 +10,7 @@ require (
|
|||||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect
|
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect
|
||||||
github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921
|
github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921
|
||||||
github.com/containernetworking/plugins v0.8.6
|
github.com/containernetworking/plugins v0.8.6
|
||||||
github.com/containers/buildah v1.15.1-0.20200708111410-d2ea9429455d
|
github.com/containers/buildah v1.15.1-0.20200731151214-29f4d01c621c
|
||||||
github.com/containers/common v0.18.0
|
github.com/containers/common v0.18.0
|
||||||
github.com/containers/conmon v2.0.19+incompatible
|
github.com/containers/conmon v2.0.19+incompatible
|
||||||
github.com/containers/image/v5 v5.5.1
|
github.com/containers/image/v5 v5.5.1
|
||||||
@ -62,7 +62,6 @@ require (
|
|||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299
|
||||||
golang.org/x/text v0.3.3 // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.3.0
|
gopkg.in/yaml.v2 v2.3.0
|
||||||
k8s.io/api v0.18.6
|
k8s.io/api v0.18.6
|
||||||
k8s.io/apimachinery v0.18.6
|
k8s.io/apimachinery v0.18.6
|
||||||
|
8
go.sum
8
go.sum
@ -70,8 +70,8 @@ github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921 h1:eUMd8
|
|||||||
github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||||
github.com/containernetworking/plugins v0.8.6 h1:npZTLiMa4CRn6m5P9+1Dz4O1j0UeFbm8VYN6dlsw568=
|
github.com/containernetworking/plugins v0.8.6 h1:npZTLiMa4CRn6m5P9+1Dz4O1j0UeFbm8VYN6dlsw568=
|
||||||
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
|
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
|
||||||
github.com/containers/buildah v1.15.1-0.20200708111410-d2ea9429455d h1:HgJJn1UBFjM464NpEmgLwVje5vSF/fBYAdLLoww9HgU=
|
github.com/containers/buildah v1.15.1-0.20200731151214-29f4d01c621c h1:+V9RQOhg1LyhyHHU33OVjO+Uan1MoVbkjufH8E/BeLU=
|
||||||
github.com/containers/buildah v1.15.1-0.20200708111410-d2ea9429455d/go.mod h1:HUAiD1mCGPFPcIuk5zls1LElLhXo7Q3hWDwheojjyAs=
|
github.com/containers/buildah v1.15.1-0.20200731151214-29f4d01c621c/go.mod h1:XVOKQHd1sP/7tFpCXIaNsUJZdTNCwVZ7YZiLnnEfrVg=
|
||||||
github.com/containers/common v0.15.2/go.mod h1:rhpXuGLTEKsk/xX/x0iKGHjRadMHpBd2ZiNDugwXPEM=
|
github.com/containers/common v0.15.2/go.mod h1:rhpXuGLTEKsk/xX/x0iKGHjRadMHpBd2ZiNDugwXPEM=
|
||||||
github.com/containers/common v0.18.0 h1:pZB6f17N5QV43TcT06gtx1lb0rxd/4StFdVhP9CtgQg=
|
github.com/containers/common v0.18.0 h1:pZB6f17N5QV43TcT06gtx1lb0rxd/4StFdVhP9CtgQg=
|
||||||
github.com/containers/common v0.18.0/go.mod h1:H2Wqvx6wkqdzT4RcTCqIG4W0HSOZwUbbNiUTX1+VohU=
|
github.com/containers/common v0.18.0/go.mod h1:H2Wqvx6wkqdzT4RcTCqIG4W0HSOZwUbbNiUTX1+VohU=
|
||||||
@ -83,6 +83,8 @@ github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDpl
|
|||||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
|
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
|
||||||
github.com/containers/ocicrypt v1.0.2 h1:Q0/IPs8ohfbXNxEfyJ2pFVmvJu5BhqJUAmc6ES9NKbo=
|
github.com/containers/ocicrypt v1.0.2 h1:Q0/IPs8ohfbXNxEfyJ2pFVmvJu5BhqJUAmc6ES9NKbo=
|
||||||
github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNjsqWarIUce4M=
|
github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNjsqWarIUce4M=
|
||||||
|
github.com/containers/ocicrypt v1.0.3 h1:vYgl+RZ9Q3DPMuTfxmN+qp0X2Bj52uuY2vnt6GzVe1c=
|
||||||
|
github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g=
|
||||||
github.com/containers/psgo v1.5.1 h1:MQNb7FLbXqBdqz6u4lI2QWizVz4RSTzs1+Nk9XT1iVA=
|
github.com/containers/psgo v1.5.1 h1:MQNb7FLbXqBdqz6u4lI2QWizVz4RSTzs1+Nk9XT1iVA=
|
||||||
github.com/containers/psgo v1.5.1/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
|
github.com/containers/psgo v1.5.1/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
|
||||||
github.com/containers/storage v1.20.2/go.mod h1:oOB9Ie8OVPojvoaKWEGSEtHbXUAs+tSyr7RO7ZGteMc=
|
github.com/containers/storage v1.20.2/go.mod h1:oOB9Ie8OVPojvoaKWEGSEtHbXUAs+tSyr7RO7ZGteMc=
|
||||||
@ -479,6 +481,8 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
|||||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
|
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
|
||||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
|
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.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||||
|
58
vendor/github.com/containers/buildah/.cirrus.yml
generated
vendored
58
vendor/github.com/containers/buildah/.cirrus.yml
generated
vendored
@ -27,7 +27,7 @@ env:
|
|||||||
####
|
####
|
||||||
# GCE project where images live
|
# GCE project where images live
|
||||||
IMAGE_PROJECT: "libpod-218412"
|
IMAGE_PROJECT: "libpod-218412"
|
||||||
# See https://github.com/containers/libpod/blob/master/contrib/cirrus/README.md#test_build_cache_images_task-task
|
# See https://github.com/containers/podman/blob/master/contrib/cirrus/README.md#test_build_cache_images_task-task
|
||||||
FEDORA_NAME: "fedora-32"
|
FEDORA_NAME: "fedora-32"
|
||||||
PRIOR_FEDORA_NAME: "fedora-31"
|
PRIOR_FEDORA_NAME: "fedora-31"
|
||||||
UBUNTU_NAME: "ubuntu-20"
|
UBUNTU_NAME: "ubuntu-20"
|
||||||
@ -111,17 +111,32 @@ gce_instance:
|
|||||||
# not supported by bors-ng
|
# not supported by bors-ng
|
||||||
# allow_failures: $CI == $CI
|
# allow_failures: $CI == $CI
|
||||||
|
|
||||||
timeout_in: 30m
|
timeout_in: 45m
|
||||||
|
|
||||||
setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}'
|
setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}'
|
||||||
build_script: '${SCRIPT_BASE}/build.sh |& ${_TIMESTAMP}'
|
build_script: '${SCRIPT_BASE}/build.sh |& ${_TIMESTAMP}'
|
||||||
# FIXME: These tests mostly/always fail
|
unit_test_script: '${SCRIPT_BASE}/test.sh unit |& ${_TIMESTAMP}'
|
||||||
unit_test_script: '${SCRIPT_BASE}/test.sh unit |& ${_TIMESTAMP} || true'
|
|
||||||
|
|
||||||
binary_artifacts:
|
binary_artifacts:
|
||||||
path: ./bin/*
|
path: ./bin/*
|
||||||
|
|
||||||
|
|
||||||
|
'cirrus-ci/only_prs/conformance_task':
|
||||||
|
gce_instance: # Only need to specify differences from defaults (above)
|
||||||
|
image_name: "${UBUNTU_CACHE_IMAGE_NAME}"
|
||||||
|
|
||||||
|
# see bors.toml
|
||||||
|
skip: $CIRRUS_BRANCH =~ ".*\.tmp"
|
||||||
|
|
||||||
|
# don't fail the PR when we fail until #2480 is merged
|
||||||
|
allow_failures: true
|
||||||
|
|
||||||
|
timeout_in: 20m
|
||||||
|
|
||||||
|
setup_script: '${SCRIPT_BASE}/setup.sh |& ${_TIMESTAMP}'
|
||||||
|
conformance_test_script: '${SCRIPT_BASE}/test.sh conformance |& ${_TIMESTAMP}'
|
||||||
|
|
||||||
|
|
||||||
# This task runs `make vendor` followed by ./hack/tree_status.sh to check
|
# This task runs `make vendor` followed by ./hack/tree_status.sh to check
|
||||||
# whether the git tree is clean. The reasoning for that is to make sure
|
# whether the git tree is clean. The reasoning for that is to make sure
|
||||||
# that the vendor.conf, the code and the vendored packages in ./vendor are
|
# that the vendor.conf, the code and the vendored packages in ./vendor are
|
||||||
@ -253,3 +268,38 @@ gce_instance:
|
|||||||
memory: 1
|
memory: 1
|
||||||
|
|
||||||
script: /bin/true
|
script: /bin/true
|
||||||
|
|
||||||
|
# Build the static binary
|
||||||
|
'cirrus-ci/only_prs/static_binary_task':
|
||||||
|
depends_on:
|
||||||
|
- "cirrus-ci/only_prs/gate"
|
||||||
|
|
||||||
|
gce_instance:
|
||||||
|
image_name: "${FEDORA_CACHE_IMAGE_NAME}"
|
||||||
|
cpu: 8
|
||||||
|
memory: 12
|
||||||
|
disk: 200
|
||||||
|
|
||||||
|
init_script: |
|
||||||
|
set -ex
|
||||||
|
setenforce 0
|
||||||
|
growpart /dev/sda 1 || true
|
||||||
|
resize2fs /dev/sda1 || true
|
||||||
|
yum -y install podman
|
||||||
|
|
||||||
|
nix_cache:
|
||||||
|
folder: '.cache'
|
||||||
|
fingerprint_script: |
|
||||||
|
echo "nix-v1-$(sha1sum nix/nixpkgs.json | head -c 40)"
|
||||||
|
|
||||||
|
build_script: |
|
||||||
|
set -ex
|
||||||
|
mkdir -p /nix
|
||||||
|
mkdir -p .cache
|
||||||
|
mount --bind .cache /nix
|
||||||
|
if [[ -z $(ls -A /nix) ]]; then podman run --rm --privileged -ti -v /:/mnt nixos/nix cp -rfT /nix /mnt/nix; fi
|
||||||
|
podman run --rm --privileged -ti -v /nix:/nix -v ${PWD}:${PWD} -w ${PWD} nixos/nix nix --print-build-logs --option cores 8 --option max-jobs 8 build --file nix/
|
||||||
|
chown -Rf $(whoami) .cache
|
||||||
|
|
||||||
|
binaries_artifacts:
|
||||||
|
path: "result/bin/buildah"
|
||||||
|
1
vendor/github.com/containers/buildah/.gitignore
generated
vendored
1
vendor/github.com/containers/buildah/.gitignore
generated
vendored
@ -6,5 +6,6 @@ docs/buildah*.1
|
|||||||
tests/tools/build
|
tests/tools/build
|
||||||
Dockerfile*
|
Dockerfile*
|
||||||
!/tests/bud/*/Dockerfile*
|
!/tests/bud/*/Dockerfile*
|
||||||
|
!/tests/conformance/**/Dockerfile*
|
||||||
*.swp
|
*.swp
|
||||||
result
|
result
|
||||||
|
23
vendor/github.com/containers/buildah/Makefile
generated
vendored
23
vendor/github.com/containers/buildah/Makefile
generated
vendored
@ -35,16 +35,25 @@ LIBSECCOMP_COMMIT := release-2.3
|
|||||||
|
|
||||||
EXTRA_LDFLAGS ?=
|
EXTRA_LDFLAGS ?=
|
||||||
LDFLAGS := -ldflags '-X main.GitCommit=$(GIT_COMMIT) -X main.buildInfo=$(SOURCE_DATE_EPOCH) -X main.cniVersion=$(CNI_COMMIT) $(EXTRA_LDFLAGS)'
|
LDFLAGS := -ldflags '-X main.GitCommit=$(GIT_COMMIT) -X main.buildInfo=$(SOURCE_DATE_EPOCH) -X main.cniVersion=$(CNI_COMMIT) $(EXTRA_LDFLAGS)'
|
||||||
SOURCES=*.go imagebuildah/*.go bind/*.go chroot/*.go cmd/buildah/*.go docker/*.go pkg/blobcache/*.go pkg/cli/*.go pkg/parse/*.go util/*.go
|
SOURCES=*.go imagebuildah/*.go bind/*.go chroot/*.go cmd/buildah/*.go copier/*.go docker/*.go pkg/blobcache/*.go pkg/cli/*.go pkg/parse/*.go util/*.go
|
||||||
|
|
||||||
LINTFLAGS ?=
|
LINTFLAGS ?=
|
||||||
|
|
||||||
all: bin/buildah bin/imgtype docs
|
all: bin/buildah bin/imgtype docs
|
||||||
|
|
||||||
|
# Update nix/nixpkgs.json its latest stable commit
|
||||||
|
.PHONY: nixpkgs
|
||||||
nixpkgs:
|
nixpkgs:
|
||||||
@nix run -f channel:nixpkgs-unstable nix-prefetch-git -c nix-prefetch-git \
|
@nix run -f channel:nixos-20.03 nix-prefetch-git -c nix-prefetch-git \
|
||||||
--no-deepClone https://github.com/nixos/nixpkgs > nix/nixpkgs.json
|
--no-deepClone https://github.com/nixos/nixpkgs > nix/nixpkgs.json
|
||||||
|
|
||||||
|
# Build statically linked binary
|
||||||
|
.PHONY: static
|
||||||
|
static:
|
||||||
|
@nix build -f nix/
|
||||||
|
mkdir -p ./bin
|
||||||
|
cp -rfp ./result/bin/* ./bin/
|
||||||
|
|
||||||
.PHONY: bin/buildah
|
.PHONY: bin/buildah
|
||||||
bin/buildah: $(SOURCES)
|
bin/buildah: $(SOURCES)
|
||||||
$(GO_BUILD) $(LDFLAGS) -o $@ $(BUILDFLAGS) ./cmd/buildah
|
$(GO_BUILD) $(LDFLAGS) -o $@ $(BUILDFLAGS) ./cmd/buildah
|
||||||
@ -125,20 +134,24 @@ install.completions:
|
|||||||
install.runc:
|
install.runc:
|
||||||
install -m 755 ../../opencontainers/runc/runc $(DESTDIR)/$(BINDIR)/
|
install -m 755 ../../opencontainers/runc/runc $(DESTDIR)/$(BINDIR)/
|
||||||
|
|
||||||
|
.PHONY: test-conformance
|
||||||
|
test-conformance:
|
||||||
|
$(GO_TEST) -v -tags "$(STORAGETAGS) $(SECURITYTAGS)" -cover -timeout 15m ./tests/conformance
|
||||||
|
|
||||||
.PHONY: test-integration
|
.PHONY: test-integration
|
||||||
test-integration: install.tools
|
test-integration: install.tools
|
||||||
./tests/tools/build/ginkgo $(BUILDFLAGS) -v tests/e2e/.
|
./tests/tools/build/ginkgo $(BUILDFLAGS) -v tests/e2e/.
|
||||||
cd tests; ./test_runner.sh
|
cd tests; ./test_runner.sh
|
||||||
|
|
||||||
tests/testreport/testreport: tests/testreport/testreport.go
|
tests/testreport/testreport: tests/testreport/testreport.go
|
||||||
$(GO_BUILD) -ldflags "-linkmode external -extldflags -static" -tags "$(STORAGETAGS) $(SECURITYTAGS)" -o tests/testreport/testreport ./tests/testreport
|
$(GO_BUILD) -ldflags "-linkmode external -extldflags -static" -tags "$(STORAGETAGS) $(SECURITYTAGS)" -o tests/testreport/testreport ./tests/testreport/testreport.go
|
||||||
|
|
||||||
.PHONY: test-unit
|
.PHONY: test-unit
|
||||||
test-unit: tests/testreport/testreport
|
test-unit: tests/testreport/testreport
|
||||||
$(GO_TEST) -v -tags "$(STORAGETAGS) $(SECURITYTAGS)" -race $(shell $(GO) list ./... | grep -v vendor | grep -v tests | grep -v cmd)
|
$(GO_TEST) -v -tags "$(STORAGETAGS) $(SECURITYTAGS)" -cover -race $(shell $(GO) list ./... | grep -v vendor | grep -v tests | grep -v cmd) -timeout 40m
|
||||||
tmp=$(shell mktemp -d) ; \
|
tmp=$(shell mktemp -d) ; \
|
||||||
mkdir -p $$tmp/root $$tmp/runroot; \
|
mkdir -p $$tmp/root $$tmp/runroot; \
|
||||||
$(GO_TEST) -v -tags "$(STORAGETAGS) $(SECURITYTAGS)" ./cmd/buildah -args -root $$tmp/root -runroot $$tmp/runroot -storage-driver vfs -signature-policy $(shell pwd)/tests/policy.json -registries-conf $(shell pwd)/tests/registries.conf
|
$(GO_TEST) -v -tags "$(STORAGETAGS) $(SECURITYTAGS)" -cover -race ./cmd/buildah -args --root $$tmp/root --runroot $$tmp/runroot --storage-driver vfs --signature-policy $(shell pwd)/tests/policy.json --registries-conf $(shell pwd)/tests/registries.conf
|
||||||
|
|
||||||
vendor-in-container:
|
vendor-in-container:
|
||||||
podman run --privileged --rm --env HOME=/root -v `pwd`:/src -w /src docker.io/library/golang:1.13 make vendor
|
podman run --privileged --rm --env HOME=/root -v `pwd`:/src -w /src docker.io/library/golang:1.13 make vendor
|
||||||
|
2
vendor/github.com/containers/buildah/README.md
generated
vendored
2
vendor/github.com/containers/buildah/README.md
generated
vendored
@ -41,7 +41,7 @@ Buildah and Podman are two complementary open-source projects that are
|
|||||||
available on most Linux platforms and both projects reside at
|
available on most Linux platforms and both projects reside at
|
||||||
[GitHub.com](https://github.com) with Buildah
|
[GitHub.com](https://github.com) with Buildah
|
||||||
[here](https://github.com/containers/buildah) and Podman
|
[here](https://github.com/containers/buildah) and Podman
|
||||||
[here](https://github.com/containers/libpod). Both, Buildah and Podman are
|
[here](https://github.com/containers/podman). Both, Buildah and Podman are
|
||||||
command line tools that work on Open Container Initiative (OCI) images and
|
command line tools that work on Open Container Initiative (OCI) images and
|
||||||
containers. The two projects differentiate in their specialization.
|
containers. The two projects differentiate in their specialization.
|
||||||
|
|
||||||
|
11
vendor/github.com/containers/buildah/chroot/run.go
generated
vendored
11
vendor/github.com/containers/buildah/chroot/run.go
generated
vendored
@ -7,6 +7,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -741,12 +742,15 @@ func runUsingChrootExecMain() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
setgroups, _ := ioutil.ReadFile("/proc/self/setgroups")
|
||||||
|
if strings.Trim(string(setgroups), "\n") != "deny" {
|
||||||
logrus.Debugf("clearing supplemental groups")
|
logrus.Debugf("clearing supplemental groups")
|
||||||
if err = syscall.Setgroups([]int{}); err != nil {
|
if err = syscall.Setgroups([]int{}); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error clearing supplemental groups list: %v", err)
|
fmt.Fprintf(os.Stderr, "error clearing supplemental groups list: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logrus.Debugf("setting gid")
|
logrus.Debugf("setting gid")
|
||||||
if err = syscall.Setresgid(int(user.GID), int(user.GID), int(user.GID)); err != nil {
|
if err = syscall.Setresgid(int(user.GID), int(user.GID), int(user.GID)); err != nil {
|
||||||
@ -1093,7 +1097,8 @@ func setupChrootBindMounts(spec *specs.Spec, bundlePath string) (undoBinds func(
|
|||||||
}
|
}
|
||||||
subSys := filepath.Join(spec.Root.Path, m.Mountpoint)
|
subSys := filepath.Join(spec.Root.Path, m.Mountpoint)
|
||||||
if err := unix.Mount(m.Mountpoint, subSys, "bind", sysFlags, ""); err != nil {
|
if err := unix.Mount(m.Mountpoint, subSys, "bind", sysFlags, ""); err != nil {
|
||||||
return undoBinds, errors.Wrapf(err, "error bind mounting /sys from host into mount namespace")
|
logrus.Warningf("could not bind mount %q, skipping: %v", m.Mountpoint, err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if err := makeReadOnly(subSys, sysFlags); err != nil {
|
if err := makeReadOnly(subSys, sysFlags); err != nil {
|
||||||
return undoBinds, err
|
return undoBinds, err
|
||||||
@ -1101,10 +1106,6 @@ func setupChrootBindMounts(spec *specs.Spec, bundlePath string) (undoBinds func(
|
|||||||
}
|
}
|
||||||
logrus.Debugf("bind mounted %q to %q", "/sys", filepath.Join(spec.Root.Path, "/sys"))
|
logrus.Debugf("bind mounted %q to %q", "/sys", filepath.Join(spec.Root.Path, "/sys"))
|
||||||
|
|
||||||
// Add /sys/fs/selinux to the set of masked paths, to ensure that we don't have processes
|
|
||||||
// attempting to interact with labeling, when they aren't allowed to do so.
|
|
||||||
spec.Linux.MaskedPaths = append(spec.Linux.MaskedPaths, "/sys/fs/selinux")
|
|
||||||
|
|
||||||
// Bind mount in everything we've been asked to mount.
|
// Bind mount in everything we've been asked to mount.
|
||||||
for _, m := range spec.Mounts {
|
for _, m := range spec.Mounts {
|
||||||
// Skip anything that we just mounted.
|
// Skip anything that we just mounted.
|
||||||
|
228
vendor/github.com/containers/buildah/digester.go
generated
vendored
228
vendor/github.com/containers/buildah/digester.go
generated
vendored
@ -1,63 +1,255 @@
|
|||||||
package buildah
|
package buildah
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"strings"
|
"io"
|
||||||
|
"sync"
|
||||||
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type singleDigester struct {
|
type digester interface {
|
||||||
|
io.WriteCloser
|
||||||
|
ContentType() string
|
||||||
|
Digest() digest.Digest
|
||||||
|
}
|
||||||
|
|
||||||
|
// A simple digester just digests its content as-is.
|
||||||
|
type simpleDigester struct {
|
||||||
digester digest.Digester
|
digester digest.Digester
|
||||||
prefix string
|
hasher hash.Hash
|
||||||
|
contentType string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSimpleDigester(contentType string) digester {
|
||||||
|
finalDigester := digest.Canonical.Digester()
|
||||||
|
return &simpleDigester{
|
||||||
|
digester: finalDigester,
|
||||||
|
hasher: finalDigester.Hash(),
|
||||||
|
contentType: contentType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *simpleDigester) ContentType() string {
|
||||||
|
return s.contentType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *simpleDigester) Write(p []byte) (int, error) {
|
||||||
|
return s.hasher.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *simpleDigester) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *simpleDigester) Digest() digest.Digest {
|
||||||
|
return s.digester.Digest()
|
||||||
|
}
|
||||||
|
|
||||||
|
// A tarFilterer passes a tarball through to an io.WriteCloser, potentially
|
||||||
|
// modifying headers as it goes.
|
||||||
|
type tarFilterer struct {
|
||||||
|
wg sync.WaitGroup
|
||||||
|
pipeWriter *io.PipeWriter
|
||||||
|
closedLock sync.Mutex
|
||||||
|
closed bool
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tarFilterer) Write(p []byte) (int, error) {
|
||||||
|
return t.pipeWriter.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tarFilterer) Close() error {
|
||||||
|
t.closedLock.Lock()
|
||||||
|
if t.closed {
|
||||||
|
t.closedLock.Unlock()
|
||||||
|
return errors.Errorf("tar filter is already closed")
|
||||||
|
}
|
||||||
|
t.closed = true
|
||||||
|
t.closedLock.Unlock()
|
||||||
|
err := t.pipeWriter.Close()
|
||||||
|
t.wg.Wait()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "error closing filter pipe")
|
||||||
|
}
|
||||||
|
return t.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTarFilterer passes one or more tar archives through to an io.WriteCloser
|
||||||
|
// as a single archive, potentially calling filter to modify headers and
|
||||||
|
// contents as it goes.
|
||||||
|
func newTarFilterer(writeCloser io.WriteCloser, filter func(hdr *tar.Header) (skip, replaceContents bool, replacementContents io.Reader)) io.WriteCloser {
|
||||||
|
pipeReader, pipeWriter := io.Pipe()
|
||||||
|
tarWriter := tar.NewWriter(writeCloser)
|
||||||
|
filterer := &tarFilterer{
|
||||||
|
pipeWriter: pipeWriter,
|
||||||
|
}
|
||||||
|
filterer.wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
filterer.closedLock.Lock()
|
||||||
|
closed := filterer.closed
|
||||||
|
filterer.closedLock.Unlock()
|
||||||
|
for !closed {
|
||||||
|
tarReader := tar.NewReader(pipeReader)
|
||||||
|
hdr, err := tarReader.Next()
|
||||||
|
for err == nil {
|
||||||
|
var skip, replaceContents bool
|
||||||
|
var replacementContents io.Reader
|
||||||
|
if filter != nil {
|
||||||
|
skip, replaceContents, replacementContents = filter(hdr)
|
||||||
|
}
|
||||||
|
if !skip {
|
||||||
|
err = tarWriter.WriteHeader(hdr)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrapf(err, "error filtering tar header for %q", hdr.Name)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if hdr.Size != 0 {
|
||||||
|
var n int64
|
||||||
|
var copyErr error
|
||||||
|
if replaceContents {
|
||||||
|
n, copyErr = io.CopyN(tarWriter, replacementContents, hdr.Size)
|
||||||
|
} else {
|
||||||
|
n, copyErr = io.Copy(tarWriter, tarReader)
|
||||||
|
}
|
||||||
|
if copyErr != nil {
|
||||||
|
err = errors.Wrapf(copyErr, "error copying content for %q", hdr.Name)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if n != hdr.Size {
|
||||||
|
err = errors.Errorf("error filtering content for %q: expected %d bytes, got %d bytes", hdr.Name, hdr.Size, n)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hdr, err = tarReader.Next()
|
||||||
|
}
|
||||||
|
if err != io.EOF {
|
||||||
|
filterer.err = errors.Wrapf(err, "error reading tar archive")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
filterer.closedLock.Lock()
|
||||||
|
closed = filterer.closed
|
||||||
|
filterer.closedLock.Unlock()
|
||||||
|
}
|
||||||
|
pipeReader.Close()
|
||||||
|
tarWriter.Close()
|
||||||
|
writeCloser.Close()
|
||||||
|
filterer.wg.Done()
|
||||||
|
}()
|
||||||
|
return filterer
|
||||||
|
}
|
||||||
|
|
||||||
|
// A tar digester digests an archive, modifying the headers it digests by
|
||||||
|
// calling a specified function to potentially modify the header that it's
|
||||||
|
// about to write.
|
||||||
|
type tarDigester struct {
|
||||||
|
isOpen bool
|
||||||
|
nested digester
|
||||||
|
tarFilterer io.WriteCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTarDigester(contentType string) digester {
|
||||||
|
nested := newSimpleDigester(contentType)
|
||||||
|
digester := &tarDigester{
|
||||||
|
isOpen: true,
|
||||||
|
nested: nested,
|
||||||
|
tarFilterer: nested,
|
||||||
|
}
|
||||||
|
return digester
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tarDigester) ContentType() string {
|
||||||
|
return t.nested.ContentType()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tarDigester) Digest() digest.Digest {
|
||||||
|
return t.nested.Digest()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tarDigester) Write(p []byte) (int, error) {
|
||||||
|
return t.tarFilterer.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tarDigester) Close() error {
|
||||||
|
if t.isOpen {
|
||||||
|
t.isOpen = false
|
||||||
|
return t.tarFilterer.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompositeDigester can compute a digest over multiple items.
|
// CompositeDigester can compute a digest over multiple items.
|
||||||
type CompositeDigester struct {
|
type CompositeDigester struct {
|
||||||
digesters []singleDigester
|
digesters []digester
|
||||||
|
closer io.Closer
|
||||||
|
}
|
||||||
|
|
||||||
|
// closeOpenDigester closes an open sub-digester, if we have one.
|
||||||
|
func (c *CompositeDigester) closeOpenDigester() {
|
||||||
|
if c.closer != nil {
|
||||||
|
c.closer.Close()
|
||||||
|
c.closer = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restart clears all state, so that the composite digester can start over.
|
// Restart clears all state, so that the composite digester can start over.
|
||||||
func (c *CompositeDigester) Restart() {
|
func (c *CompositeDigester) Restart() {
|
||||||
|
c.closeOpenDigester()
|
||||||
c.digesters = nil
|
c.digesters = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts recording the digest for a new item. The caller should call
|
// Start starts recording the digest for a new item ("", "file", or "dir").
|
||||||
// Hash() immediately after to retrieve the new io.Writer.
|
// The caller should call Hash() immediately after to retrieve the new
|
||||||
func (c *CompositeDigester) Start(prefix string) {
|
// io.WriteCloser.
|
||||||
prefix = strings.TrimSuffix(prefix, ":")
|
func (c *CompositeDigester) Start(contentType string) {
|
||||||
c.digesters = append(c.digesters, singleDigester{digester: digest.Canonical.Digester(), prefix: prefix})
|
c.closeOpenDigester()
|
||||||
|
switch contentType {
|
||||||
|
case "":
|
||||||
|
c.digesters = append(c.digesters, newSimpleDigester(""))
|
||||||
|
case "file", "dir":
|
||||||
|
digester := newTarDigester(contentType)
|
||||||
|
c.closer = digester
|
||||||
|
c.digesters = append(c.digesters, digester)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf(`unrecognized content type: expected "", "file", or "dir", got %q`, contentType))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash returns the hasher for the current item.
|
// Hash returns the hasher for the current item.
|
||||||
func (c *CompositeDigester) Hash() hash.Hash {
|
func (c *CompositeDigester) Hash() io.WriteCloser {
|
||||||
num := len(c.digesters)
|
num := len(c.digesters)
|
||||||
if num == 0 {
|
if num == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return c.digesters[num-1].digester.Hash()
|
return c.digesters[num-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Digest returns the prefix and a composite digest over everything that's been
|
// Digest returns the content type and a composite digest over everything
|
||||||
// digested.
|
// that's been digested.
|
||||||
func (c *CompositeDigester) Digest() (string, digest.Digest) {
|
func (c *CompositeDigester) Digest() (string, digest.Digest) {
|
||||||
|
c.closeOpenDigester()
|
||||||
num := len(c.digesters)
|
num := len(c.digesters)
|
||||||
switch num {
|
switch num {
|
||||||
case 0:
|
case 0:
|
||||||
return "", ""
|
return "", ""
|
||||||
case 1:
|
case 1:
|
||||||
return c.digesters[0].prefix, c.digesters[0].digester.Digest()
|
return c.digesters[0].ContentType(), c.digesters[0].Digest()
|
||||||
default:
|
default:
|
||||||
content := ""
|
content := ""
|
||||||
for i, digester := range c.digesters {
|
for i, digester := range c.digesters {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
content += ","
|
content += ","
|
||||||
}
|
}
|
||||||
prefix := digester.prefix
|
contentType := digester.ContentType()
|
||||||
if digester.prefix != "" {
|
if contentType != "" {
|
||||||
digester.prefix += ":"
|
contentType += ":"
|
||||||
}
|
}
|
||||||
content += prefix + digester.digester.Digest().Encoded()
|
content += contentType + digester.Digest().Encoded()
|
||||||
}
|
}
|
||||||
return "multi", digest.Canonical.FromString(content)
|
return "multi", digest.Canonical.FromString(content)
|
||||||
}
|
}
|
||||||
|
8
vendor/github.com/containers/buildah/go.mod
generated
vendored
8
vendor/github.com/containers/buildah/go.mod
generated
vendored
@ -6,7 +6,7 @@ require (
|
|||||||
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784
|
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784
|
||||||
github.com/containers/common v0.15.2
|
github.com/containers/common v0.15.2
|
||||||
github.com/containers/image/v5 v5.5.1
|
github.com/containers/image/v5 v5.5.1
|
||||||
github.com/containers/ocicrypt v1.0.2
|
github.com/containers/ocicrypt v1.0.3
|
||||||
github.com/containers/storage v1.20.2
|
github.com/containers/storage v1.20.2
|
||||||
github.com/cyphar/filepath-securejoin v0.2.2
|
github.com/cyphar/filepath-securejoin v0.2.2
|
||||||
github.com/docker/distribution v2.7.1+incompatible
|
github.com/docker/distribution v2.7.1+incompatible
|
||||||
@ -17,14 +17,14 @@ require (
|
|||||||
github.com/hashicorp/go-multierror v1.0.0
|
github.com/hashicorp/go-multierror v1.0.0
|
||||||
github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07 // indirect
|
github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07 // indirect
|
||||||
github.com/mattn/go-shellwords v1.0.10
|
github.com/mattn/go-shellwords v1.0.10
|
||||||
github.com/onsi/ginkgo v1.13.0
|
github.com/onsi/ginkgo v1.14.0
|
||||||
github.com/onsi/gomega v1.10.1
|
github.com/onsi/gomega v1.10.1
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
|
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
|
||||||
github.com/opencontainers/runc v1.0.0-rc91
|
github.com/opencontainers/runc v1.0.0-rc91
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2
|
||||||
github.com/opencontainers/runtime-tools v0.9.0
|
github.com/opencontainers/runtime-tools v0.9.0
|
||||||
github.com/opencontainers/selinux v1.5.2
|
github.com/opencontainers/selinux v1.6.0
|
||||||
github.com/openshift/imagebuilder v1.1.6
|
github.com/openshift/imagebuilder v1.1.6
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/seccomp/containers-golang v0.5.0
|
github.com/seccomp/containers-golang v0.5.0
|
||||||
@ -38,6 +38,8 @@ require (
|
|||||||
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5
|
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299
|
||||||
|
golang.org/x/text v0.3.3 // indirect
|
||||||
|
k8s.io/klog v1.0.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.4.2
|
replace github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.4.2
|
||||||
|
15
vendor/github.com/containers/buildah/go.sum
generated
vendored
15
vendor/github.com/containers/buildah/go.sum
generated
vendored
@ -59,6 +59,8 @@ github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDpl
|
|||||||
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
|
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
|
||||||
github.com/containers/ocicrypt v1.0.2 h1:Q0/IPs8ohfbXNxEfyJ2pFVmvJu5BhqJUAmc6ES9NKbo=
|
github.com/containers/ocicrypt v1.0.2 h1:Q0/IPs8ohfbXNxEfyJ2pFVmvJu5BhqJUAmc6ES9NKbo=
|
||||||
github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNjsqWarIUce4M=
|
github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNjsqWarIUce4M=
|
||||||
|
github.com/containers/ocicrypt v1.0.3 h1:vYgl+RZ9Q3DPMuTfxmN+qp0X2Bj52uuY2vnt6GzVe1c=
|
||||||
|
github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g=
|
||||||
github.com/containers/storage v1.20.2 h1:tw/uKRPDnmVrluIzer3dawTFG/bTJLP8IEUyHFhltYk=
|
github.com/containers/storage v1.20.2 h1:tw/uKRPDnmVrluIzer3dawTFG/bTJLP8IEUyHFhltYk=
|
||||||
github.com/containers/storage v1.20.2/go.mod h1:oOB9Ie8OVPojvoaKWEGSEtHbXUAs+tSyr7RO7ZGteMc=
|
github.com/containers/storage v1.20.2/go.mod h1:oOB9Ie8OVPojvoaKWEGSEtHbXUAs+tSyr7RO7ZGteMc=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
@ -111,6 +113,7 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
|
|||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
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.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
|
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
|
||||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||||
@ -221,6 +224,8 @@ github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
|
|||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.13.0 h1:M76yO2HkZASFjXL0HSoZJ1AYEmQxNJmY41Jx1zNUq1Y=
|
github.com/onsi/ginkgo v1.13.0 h1:M76yO2HkZASFjXL0HSoZJ1AYEmQxNJmY41Jx1zNUq1Y=
|
||||||
github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
|
github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
|
||||||
|
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||||
|
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||||
@ -249,6 +254,8 @@ github.com/opencontainers/selinux v1.5.1 h1:jskKwSMFYqyTrHEuJgQoUlTcId0av64S6EWO
|
|||||||
github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
|
github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
|
||||||
github.com/opencontainers/selinux v1.5.2 h1:F6DgIsjgBIcDksLW4D5RG9bXok6oqZ3nvMwj4ZoFu/Q=
|
github.com/opencontainers/selinux v1.5.2 h1:F6DgIsjgBIcDksLW4D5RG9bXok6oqZ3nvMwj4ZoFu/Q=
|
||||||
github.com/opencontainers/selinux v1.5.2/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
|
github.com/opencontainers/selinux v1.5.2/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
|
||||||
|
github.com/opencontainers/selinux v1.6.0 h1:+bIAS/Za3q5FTwWym4fTB0vObnfCf3G/NC7K6Jx62mY=
|
||||||
|
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||||
github.com/openshift/imagebuilder v1.1.6 h1:1+YzRxIIefY4QqtCImx6rg+75QrKNfBoPAKxgMo/khM=
|
github.com/openshift/imagebuilder v1.1.6 h1:1+YzRxIIefY4QqtCImx6rg+75QrKNfBoPAKxgMo/khM=
|
||||||
github.com/openshift/imagebuilder v1.1.6/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
|
github.com/openshift/imagebuilder v1.1.6/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
|
||||||
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
|
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
|
||||||
@ -338,6 +345,8 @@ github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJ
|
|||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
|
||||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||||
|
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243 h1:R43TdZy32XXSXjJn7M/HhALJ9imq6ztLnChfYJpVDnM=
|
||||||
|
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
@ -353,6 +362,8 @@ go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
|||||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
|
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
|
||||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
|
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.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
@ -418,6 +429,8 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@ -478,4 +491,6 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
|||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||||
|
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
||||||
|
1
vendor/github.com/containers/buildah/imagebuildah/build.go
generated
vendored
1
vendor/github.com/containers/buildah/imagebuildah/build.go
generated
vendored
@ -132,6 +132,7 @@ type BuildOptions struct {
|
|||||||
// when handling RUN instructions. If a capability appears in both lists, it
|
// when handling RUN instructions. If a capability appears in both lists, it
|
||||||
// will be dropped.
|
// will be dropped.
|
||||||
DropCapabilities []string
|
DropCapabilities []string
|
||||||
|
// CommonBuildOpts is *required*.
|
||||||
CommonBuildOpts *buildah.CommonBuildOptions
|
CommonBuildOpts *buildah.CommonBuildOptions
|
||||||
// DefaultMountsFilePath is the file path holding the mounts to be mounted in "host-path:container-path" format
|
// DefaultMountsFilePath is the file path holding the mounts to be mounted in "host-path:container-path" format
|
||||||
DefaultMountsFilePath string
|
DefaultMountsFilePath string
|
||||||
|
46
vendor/github.com/containers/buildah/imagebuildah/executor.go
generated
vendored
46
vendor/github.com/containers/buildah/imagebuildah/executor.go
generated
vendored
@ -251,8 +251,9 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
|
|||||||
|
|
||||||
// startStage creates a new stage executor that will be referenced whenever a
|
// startStage creates a new stage executor that will be referenced whenever a
|
||||||
// COPY or ADD statement uses a --from=NAME flag.
|
// COPY or ADD statement uses a --from=NAME flag.
|
||||||
func (b *Executor) startStage(stage *imagebuilder.Stage, stages imagebuilder.Stages, output string) *StageExecutor {
|
func (b *Executor) startStage(ctx context.Context, stage *imagebuilder.Stage, stages imagebuilder.Stages, output string) *StageExecutor {
|
||||||
stageExec := &StageExecutor{
|
stageExec := &StageExecutor{
|
||||||
|
ctx: ctx,
|
||||||
executor: b,
|
executor: b,
|
||||||
index: stage.Position,
|
index: stage.Position,
|
||||||
stages: stages,
|
stages: stages,
|
||||||
@ -289,17 +290,24 @@ func (b *Executor) resolveNameToImageRef(output string) (types.ImageReference, e
|
|||||||
return imageRef, nil
|
return imageRef, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Executor) waitForStage(ctx context.Context, name string) error {
|
// waitForStage waits for an entry to be added to terminatedStage indicating
|
||||||
stage := b.stages[name]
|
// that the specified stage has finished. If there is no stage defined by that
|
||||||
if stage == nil {
|
// name, then it will return (false, nil). If there is a stage defined by that
|
||||||
return errors.Errorf("unknown stage %q", name)
|
// name, it will return true along with any error it encounters.
|
||||||
|
func (b *Executor) waitForStage(ctx context.Context, name string, stages imagebuilder.Stages) (bool, error) {
|
||||||
|
found := false
|
||||||
|
for _, otherStage := range stages {
|
||||||
|
if otherStage.Name == name || fmt.Sprintf("%d", otherStage.Position) == name {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
if b.lastError != nil {
|
if b.lastError != nil {
|
||||||
return b.lastError
|
return true, b.lastError
|
||||||
}
|
|
||||||
if stage.stage == nil {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.stagesLock.Lock()
|
b.stagesLock.Lock()
|
||||||
@ -307,13 +315,13 @@ func (b *Executor) waitForStage(ctx context.Context, name string) error {
|
|||||||
b.stagesLock.Unlock()
|
b.stagesLock.Unlock()
|
||||||
|
|
||||||
if terminated {
|
if terminated {
|
||||||
return nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
b.stagesSemaphore.Release(1)
|
b.stagesSemaphore.Release(1)
|
||||||
time.Sleep(time.Millisecond * 10)
|
time.Sleep(time.Millisecond * 10)
|
||||||
if err := b.stagesSemaphore.Acquire(ctx, 1); err != nil {
|
if err := b.stagesSemaphore.Acquire(ctx, 1); err != nil {
|
||||||
return errors.Wrapf(err, "error reacquiring job semaphore")
|
return true, errors.Wrapf(err, "error reacquiring job semaphore")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,7 +363,7 @@ func (b *Executor) buildStage(ctx context.Context, cleanupStages map[int]*StageE
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.stagesLock.Lock()
|
b.stagesLock.Lock()
|
||||||
stageExecutor := b.startStage(&stage, stages, output)
|
stageExecutor := b.startStage(ctx, &stage, stages, output)
|
||||||
b.stagesLock.Unlock()
|
b.stagesLock.Unlock()
|
||||||
|
|
||||||
// If this a single-layer build, or if it's a multi-layered
|
// If this a single-layer build, or if it's a multi-layered
|
||||||
@ -531,19 +539,19 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
|
|||||||
go func() {
|
go func() {
|
||||||
defer b.stagesSemaphore.Release(1)
|
defer b.stagesSemaphore.Release(1)
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
imageID, ref, err = b.buildStage(ctx, cleanupStages, stages, index)
|
stageID, stageRef, stageErr := b.buildStage(ctx, cleanupStages, stages, index)
|
||||||
if err != nil {
|
if stageErr != nil {
|
||||||
ch <- Result{
|
ch <- Result{
|
||||||
Index: index,
|
Index: index,
|
||||||
Error: err,
|
Error: stageErr,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ch <- Result{
|
ch <- Result{
|
||||||
Index: index,
|
Index: index,
|
||||||
ImageID: imageID,
|
ImageID: stageID,
|
||||||
Ref: ref,
|
Ref: stageRef,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -559,6 +567,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
|
|||||||
|
|
||||||
b.stagesLock.Lock()
|
b.stagesLock.Lock()
|
||||||
b.terminatedStage[stage.Name] = struct{}{}
|
b.terminatedStage[stage.Name] = struct{}{}
|
||||||
|
b.terminatedStage[fmt.Sprintf("%d", stage.Position)] = struct{}{}
|
||||||
b.stagesLock.Unlock()
|
b.stagesLock.Unlock()
|
||||||
|
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
@ -569,7 +578,9 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
|
|||||||
// If this is an intermediate stage, make a note of the ID, so
|
// If this is an intermediate stage, make a note of the ID, so
|
||||||
// that we can look it up later.
|
// that we can look it up later.
|
||||||
if r.Index < len(stages)-1 && r.ImageID != "" {
|
if r.Index < len(stages)-1 && r.ImageID != "" {
|
||||||
|
b.stagesLock.Lock()
|
||||||
b.imageMap[stage.Name] = r.ImageID
|
b.imageMap[stage.Name] = r.ImageID
|
||||||
|
b.stagesLock.Unlock()
|
||||||
// We're not populating the cache with intermediate
|
// We're not populating the cache with intermediate
|
||||||
// images, so add this one to the list of images that
|
// images, so add this one to the list of images that
|
||||||
// we'll remove later.
|
// we'll remove later.
|
||||||
@ -579,6 +590,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
|
|||||||
}
|
}
|
||||||
if r.Index == len(stages)-1 {
|
if r.Index == len(stages)-1 {
|
||||||
imageID = r.ImageID
|
imageID = r.ImageID
|
||||||
|
ref = r.Ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
generated
vendored
32
vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
generated
vendored
@ -44,6 +44,7 @@ import (
|
|||||||
// If we're naming the result of the build, only the last stage will apply that
|
// If we're naming the result of the build, only the last stage will apply that
|
||||||
// name to the image that it produces.
|
// name to the image that it produces.
|
||||||
type StageExecutor struct {
|
type StageExecutor struct {
|
||||||
|
ctx context.Context
|
||||||
executor *Executor
|
executor *Executor
|
||||||
index int
|
index int
|
||||||
stages imagebuilder.Stages
|
stages imagebuilder.Stages
|
||||||
@ -262,7 +263,7 @@ func (s *StageExecutor) volumeCacheRestore() error {
|
|||||||
// don't care about the details of where in the filesystem the content actually
|
// don't care about the details of where in the filesystem the content actually
|
||||||
// goes, because we're not actually going to add it here, so this is less
|
// goes, because we're not actually going to add it here, so this is less
|
||||||
// involved than Copy().
|
// involved than Copy().
|
||||||
func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []string, envValues []string) (string, error) {
|
func (s *StageExecutor) digestSpecifiedContent(ctx context.Context, node *parser.Node, argValues []string, envValues []string) (string, error) {
|
||||||
// No instruction: done.
|
// No instruction: done.
|
||||||
if node == nil {
|
if node == nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
@ -295,6 +296,9 @@ func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []st
|
|||||||
// container. Update the ID mappings and
|
// container. Update the ID mappings and
|
||||||
// all-content-comes-from-below-this-directory value.
|
// all-content-comes-from-below-this-directory value.
|
||||||
from := strings.TrimPrefix(flag, "--from=")
|
from := strings.TrimPrefix(flag, "--from=")
|
||||||
|
if isStage, err := s.executor.waitForStage(ctx, from, s.stages[:s.index]); isStage && err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
if other, ok := s.executor.stages[from]; ok && other.index < s.index {
|
if other, ok := s.executor.stages[from]; ok && other.index < s.index {
|
||||||
contextDir = other.mountPoint
|
contextDir = other.mountPoint
|
||||||
idMappingOptions = &other.builder.IDMappingOptions
|
idMappingOptions = &other.builder.IDMappingOptions
|
||||||
@ -422,6 +426,9 @@ func (s *StageExecutor) Copy(excludes []string, copies ...imagebuilder.Copy) err
|
|||||||
var copyExcludes []string
|
var copyExcludes []string
|
||||||
contextDir := s.executor.contextDir
|
contextDir := s.executor.contextDir
|
||||||
if len(copy.From) > 0 {
|
if len(copy.From) > 0 {
|
||||||
|
if isStage, err := s.executor.waitForStage(s.ctx, copy.From, s.stages[:s.index]); isStage && err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if other, ok := s.executor.stages[copy.From]; ok && other.index < s.index {
|
if other, ok := s.executor.stages[copy.From]; ok && other.index < s.index {
|
||||||
contextDir = other.mountPoint
|
contextDir = other.mountPoint
|
||||||
idMappingOptions = &other.builder.IDMappingOptions
|
idMappingOptions = &other.builder.IDMappingOptions
|
||||||
@ -638,9 +645,11 @@ func (s *StageExecutor) prepare(ctx context.Context, from string, initializeIBCo
|
|||||||
|
|
||||||
// Check and see if the image is a pseudonym for the end result of a
|
// Check and see if the image is a pseudonym for the end result of a
|
||||||
// previous stage, named by an AS clause in the Dockerfile.
|
// previous stage, named by an AS clause in the Dockerfile.
|
||||||
|
s.executor.stagesLock.Lock()
|
||||||
if asImageFound, ok := s.executor.imageMap[from]; ok {
|
if asImageFound, ok := s.executor.imageMap[from]; ok {
|
||||||
builderOptions.FromImage = asImageFound
|
builderOptions.FromImage = asImageFound
|
||||||
}
|
}
|
||||||
|
s.executor.stagesLock.Unlock()
|
||||||
builder, err = buildah.NewBuilder(ctx, s.executor.store, builderOptions)
|
builder, err = buildah.NewBuilder(ctx, s.executor.store, builderOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error creating build container")
|
return nil, errors.Wrapf(err, "error creating build container")
|
||||||
@ -763,16 +772,14 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||||||
// substitute that image's ID for the base image's name here. If not,
|
// substitute that image's ID for the base image's name here. If not,
|
||||||
// then go on assuming that it's just a regular image that's either in
|
// then go on assuming that it's just a regular image that's either in
|
||||||
// local storage, or one that we have to pull from a registry.
|
// local storage, or one that we have to pull from a registry.
|
||||||
for _, previousStage := range s.stages[:s.index] {
|
if isStage, err := s.executor.waitForStage(ctx, base, s.stages[:s.index]); isStage && err != nil {
|
||||||
if previousStage.Name == base {
|
|
||||||
if err := s.executor.waitForStage(ctx, previousStage.Name); err != nil {
|
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
}
|
s.executor.stagesLock.Lock()
|
||||||
}
|
|
||||||
if stageImage, isPreviousStage := s.executor.imageMap[base]; isPreviousStage {
|
if stageImage, isPreviousStage := s.executor.imageMap[base]; isPreviousStage {
|
||||||
base = stageImage
|
base = stageImage
|
||||||
}
|
}
|
||||||
|
s.executor.stagesLock.Unlock()
|
||||||
|
|
||||||
// Create the (first) working container for this stage. Reinitializing
|
// Create the (first) working container for this stage. Reinitializing
|
||||||
// the imagebuilder configuration may alter the list of steps we have,
|
// the imagebuilder configuration may alter the list of steps we have,
|
||||||
@ -876,10 +883,13 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||||||
if len(arr) != 2 {
|
if len(arr) != 2 {
|
||||||
return "", nil, errors.Errorf("%s: invalid --from flag, should be --from=<name|stage>", command)
|
return "", nil, errors.Errorf("%s: invalid --from flag, should be --from=<name|stage>", command)
|
||||||
}
|
}
|
||||||
if otherStage, ok := s.executor.stages[arr[1]]; ok && otherStage.index < s.index {
|
// If the source's name corresponds to the
|
||||||
if err := s.executor.waitForStage(ctx, otherStage.name); err != nil {
|
// result of an earlier stage, wait for that
|
||||||
|
// stage to finish being built.
|
||||||
|
if isStage, err := s.executor.waitForStage(ctx, arr[1], s.stages[:s.index]); isStage && err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
if otherStage, ok := s.executor.stages[arr[1]]; ok && otherStage.index < s.index {
|
||||||
mountPoint = otherStage.mountPoint
|
mountPoint = otherStage.mountPoint
|
||||||
} else if mountPoint, err = s.getImageRootfs(ctx, arr[1]); err != nil {
|
} else if mountPoint, err = s.getImageRootfs(ctx, arr[1]); err != nil {
|
||||||
return "", nil, errors.Errorf("%s --from=%s: no stage or image found with that name", command, arr[1])
|
return "", nil, errors.Errorf("%s --from=%s: no stage or image found with that name", command, arr[1])
|
||||||
@ -907,7 +917,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||||||
return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message)
|
return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message)
|
||||||
}
|
}
|
||||||
// In case we added content, retrieve its digest.
|
// In case we added content, retrieve its digest.
|
||||||
addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments(), ib.Config().Env)
|
addedContentDigest, err := s.digestSpecifiedContent(ctx, node, ib.Arguments(), ib.Config().Env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
@ -956,7 +966,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||||||
// cached images so far, look for one that matches what we
|
// cached images so far, look for one that matches what we
|
||||||
// expect to produce for this instruction.
|
// expect to produce for this instruction.
|
||||||
if checkForLayers && !(s.executor.squash && lastInstruction && lastStage) {
|
if checkForLayers && !(s.executor.squash && lastInstruction && lastStage) {
|
||||||
addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments(), ib.Config().Env)
|
addedContentDigest, err := s.digestSpecifiedContent(ctx, node, ib.Arguments(), ib.Config().Env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
@ -1014,7 +1024,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
|
|||||||
return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message)
|
return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message)
|
||||||
}
|
}
|
||||||
// In case we added content, retrieve its digest.
|
// In case we added content, retrieve its digest.
|
||||||
addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments(), ib.Config().Env)
|
addedContentDigest, err := s.digestSpecifiedContent(ctx, node, ib.Arguments(), ib.Config().Env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
8
vendor/github.com/containers/buildah/install.md
generated
vendored
8
vendor/github.com/containers/buildah/install.md
generated
vendored
@ -221,7 +221,7 @@ as yum, dnf or apt-get on a number of Linux distributions.
|
|||||||
|
|
||||||
Prior to installing Buildah, install the following packages on your Linux distro:
|
Prior to installing Buildah, install the following packages on your Linux distro:
|
||||||
* make
|
* make
|
||||||
* golang (Requires version 1.12 or higher.)
|
* golang (Requires version 1.13 or higher.)
|
||||||
* bats
|
* bats
|
||||||
* btrfs-progs-devel
|
* btrfs-progs-devel
|
||||||
* bzip2
|
* bzip2
|
||||||
@ -332,7 +332,7 @@ In Ubuntu zesty and xenial, you can use these commands:
|
|||||||
sudo apt-add-repository -y ppa:projectatomic/ppa
|
sudo apt-add-repository -y ppa:projectatomic/ppa
|
||||||
sudo apt-get -y -qq update
|
sudo apt-get -y -qq update
|
||||||
sudo apt-get -y install bats btrfs-tools git libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libseccomp-dev libselinux1-dev skopeo-containers go-md2man
|
sudo apt-get -y install bats btrfs-tools git libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libseccomp-dev libselinux1-dev skopeo-containers go-md2man
|
||||||
sudo apt-get -y install golang-1.12
|
sudo apt-get -y install golang-1.13
|
||||||
```
|
```
|
||||||
Then to install Buildah on Ubuntu follow the steps in this example:
|
Then to install Buildah on Ubuntu follow the steps in this example:
|
||||||
|
|
||||||
@ -342,7 +342,7 @@ Then to install Buildah on Ubuntu follow the steps in this example:
|
|||||||
export GOPATH=`pwd`
|
export GOPATH=`pwd`
|
||||||
git clone https://github.com/containers/buildah ./src/github.com/containers/buildah
|
git clone https://github.com/containers/buildah ./src/github.com/containers/buildah
|
||||||
cd ./src/github.com/containers/buildah
|
cd ./src/github.com/containers/buildah
|
||||||
PATH=/usr/lib/go-1.12/bin:$PATH make runc all SECURITYTAGS="apparmor seccomp"
|
PATH=/usr/lib/go-1.13/bin:$PATH make runc all SECURITYTAGS="apparmor seccomp"
|
||||||
sudo make install install.runc
|
sudo make install install.runc
|
||||||
buildah --help
|
buildah --help
|
||||||
```
|
```
|
||||||
@ -433,7 +433,7 @@ cat /usr/share/containers/mounts.conf
|
|||||||
|
|
||||||
`/usr/share/containers/seccomp.json`
|
`/usr/share/containers/seccomp.json`
|
||||||
|
|
||||||
seccomp.json contains the whitelist of seccomp rules to be allowed inside of
|
seccomp.json contains the list of seccomp rules to be allowed inside of
|
||||||
containers. This file is usually provided by the containers-common package.
|
containers. This file is usually provided by the containers-common package.
|
||||||
|
|
||||||
The link above takes you to the seccomp.json
|
The link above takes you to the seccomp.json
|
||||||
|
5
vendor/github.com/containers/buildah/pkg/blobcache/blobcache.go
generated
vendored
5
vendor/github.com/containers/buildah/pkg/blobcache/blobcache.go
generated
vendored
@ -275,12 +275,11 @@ func (s *blobCacheSource) LayerInfosForCopy(ctx context.Context, instanceDigest
|
|||||||
return nil, errors.Wrapf(err, "error getting layer infos for copying image %q through cache", transports.ImageName(s.reference))
|
return nil, errors.Wrapf(err, "error getting layer infos for copying image %q through cache", transports.ImageName(s.reference))
|
||||||
}
|
}
|
||||||
if infos == nil {
|
if infos == nil {
|
||||||
image, err := s.reference.NewImage(ctx, &s.sys)
|
img, err := image.FromUnparsedImage(ctx, &s.sys, image.UnparsedInstance(s.source, instanceDigest))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error opening image to get layer infos for copying image %q through cache", transports.ImageName(s.reference))
|
return nil, errors.Wrapf(err, "error opening image to get layer infos for copying image %q through cache", transports.ImageName(s.reference))
|
||||||
}
|
}
|
||||||
defer image.Close()
|
infos = img.LayerInfos()
|
||||||
infos = image.LayerInfos()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if canReplaceBlobs && s.reference.compress != types.PreserveOriginal {
|
if canReplaceBlobs && s.reference.compress != types.PreserveOriginal {
|
||||||
|
14
vendor/github.com/containers/buildah/pkg/parse/parse.go
generated
vendored
14
vendor/github.com/containers/buildah/pkg/parse/parse.go
generated
vendored
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/containers/buildah"
|
"github.com/containers/buildah"
|
||||||
"github.com/containers/image/v5/types"
|
"github.com/containers/image/v5/types"
|
||||||
"github.com/containers/storage/pkg/idtools"
|
"github.com/containers/storage/pkg/idtools"
|
||||||
|
"github.com/containers/storage/pkg/unshare"
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -342,6 +343,9 @@ func GetBindMount(args []string) (specs.Mount, error) {
|
|||||||
// TODO: detect duplication of these options.
|
// TODO: detect duplication of these options.
|
||||||
// (Is this necessary?)
|
// (Is this necessary?)
|
||||||
newMount.Options = append(newMount.Options, kv[0])
|
newMount.Options = append(newMount.Options, kv[0])
|
||||||
|
case "readonly":
|
||||||
|
// Alias for "ro"
|
||||||
|
newMount.Options = append(newMount.Options, "ro")
|
||||||
case "shared", "rshared", "private", "rprivate", "slave", "rslave", "Z", "z":
|
case "shared", "rshared", "private", "rprivate", "slave", "rslave", "Z", "z":
|
||||||
newMount.Options = append(newMount.Options, kv[0])
|
newMount.Options = append(newMount.Options, kv[0])
|
||||||
case "bind-propagation":
|
case "bind-propagation":
|
||||||
@ -367,6 +371,10 @@ func GetBindMount(args []string) (specs.Mount, error) {
|
|||||||
}
|
}
|
||||||
newMount.Destination = kv[1]
|
newMount.Destination = kv[1]
|
||||||
setDest = true
|
setDest = true
|
||||||
|
case "consistency":
|
||||||
|
// Option for OS X only, has no meaning on other platforms
|
||||||
|
// and can thus be safely ignored.
|
||||||
|
// See also the handling of the equivalent "delegated" and "cached" in ValidateVolumeOpts
|
||||||
default:
|
default:
|
||||||
return newMount, errors.Wrapf(errBadMntOption, kv[0])
|
return newMount, errors.Wrapf(errBadMntOption, kv[0])
|
||||||
}
|
}
|
||||||
@ -403,6 +411,9 @@ func GetTmpfsMount(args []string) (specs.Mount, error) {
|
|||||||
switch kv[0] {
|
switch kv[0] {
|
||||||
case "ro", "nosuid", "nodev", "noexec":
|
case "ro", "nosuid", "nodev", "noexec":
|
||||||
newMount.Options = append(newMount.Options, kv[0])
|
newMount.Options = append(newMount.Options, kv[0])
|
||||||
|
case "readonly":
|
||||||
|
// Alias for "ro"
|
||||||
|
newMount.Options = append(newMount.Options, "ro")
|
||||||
case "tmpfs-mode":
|
case "tmpfs-mode":
|
||||||
if len(kv) == 1 {
|
if len(kv) == 1 {
|
||||||
return newMount, errors.Wrapf(optionArgError, kv[0])
|
return newMount, errors.Wrapf(optionArgError, kv[0])
|
||||||
@ -907,6 +918,9 @@ func defaultIsolation() (buildah.Isolation, error) {
|
|||||||
return 0, errors.Errorf("unrecognized $BUILDAH_ISOLATION value %q", isolation)
|
return 0, errors.Errorf("unrecognized $BUILDAH_ISOLATION value %q", isolation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if unshare.IsRootless() {
|
||||||
|
return buildah.IsolationOCIRootless, nil
|
||||||
|
}
|
||||||
return buildah.IsolationDefault, nil
|
return buildah.IsolationDefault, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
vendor/github.com/containers/buildah/run_linux.go
generated
vendored
23
vendor/github.com/containers/buildah/run_linux.go
generated
vendored
@ -394,7 +394,10 @@ func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, bundlePath st
|
|||||||
for _, specMount := range spec.Mounts {
|
for _, specMount := range spec.Mounts {
|
||||||
// Override some of the mounts from the generated list if we're doing different things with namespaces.
|
// Override some of the mounts from the generated list if we're doing different things with namespaces.
|
||||||
if specMount.Destination == "/dev/shm" {
|
if specMount.Destination == "/dev/shm" {
|
||||||
specMount.Options = []string{"nosuid", "noexec", "nodev", "mode=1777", "size=" + shmSize}
|
specMount.Options = []string{"nosuid", "noexec", "nodev", "mode=1777"}
|
||||||
|
if shmSize != "" {
|
||||||
|
specMount.Options = append(specMount.Options, "size="+shmSize)
|
||||||
|
}
|
||||||
if hostIPC && !hostUser {
|
if hostIPC && !hostUser {
|
||||||
if _, err := os.Stat("/dev/shm"); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat("/dev/shm"); err != nil && os.IsNotExist(err) {
|
||||||
logrus.Debugf("/dev/shm is not present, not binding into container")
|
logrus.Debugf("/dev/shm is not present, not binding into container")
|
||||||
@ -841,15 +844,10 @@ func runUsingRuntime(isolation Isolation, options RunOptions, configureNetwork b
|
|||||||
stopped := false
|
stopped := false
|
||||||
defer func() {
|
defer func() {
|
||||||
if !stopped {
|
if !stopped {
|
||||||
err2 := kill.Run()
|
if err2 := kill.Run(); err2 != nil {
|
||||||
if err2 != nil {
|
|
||||||
if err == nil {
|
|
||||||
err = errors.Wrapf(err2, "error stopping container")
|
|
||||||
} else {
|
|
||||||
logrus.Infof("error stopping container: %v", err2)
|
logrus.Infof("error stopping container: %v", err2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Wait for the container to exit.
|
// Wait for the container to exit.
|
||||||
@ -1779,6 +1777,8 @@ func setupMaskedPaths(g *generate.Generator) {
|
|||||||
"/proc/sched_debug",
|
"/proc/sched_debug",
|
||||||
"/proc/scsi",
|
"/proc/scsi",
|
||||||
"/sys/firmware",
|
"/sys/firmware",
|
||||||
|
"/sys/fs/selinux",
|
||||||
|
"/sys/dev",
|
||||||
} {
|
} {
|
||||||
g.AddLinuxMaskedPaths(mp)
|
g.AddLinuxMaskedPaths(mp)
|
||||||
}
|
}
|
||||||
@ -1966,7 +1966,7 @@ func (b *Builder) configureEnvironment(g *generate.Generator, options RunOptions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, envSpec := range append(append(defaultEnv, b.Env()...), options.Env...) {
|
for _, envSpec := range util.MergeEnv(util.MergeEnv(defaultEnv, b.Env()), options.Env) {
|
||||||
env := strings.SplitN(envSpec, "=", 2)
|
env := strings.SplitN(envSpec, "=", 2)
|
||||||
if len(env) > 1 {
|
if len(env) > 1 {
|
||||||
g.AddProcessEnv(env[0], env[1])
|
g.AddProcessEnv(env[0], env[1])
|
||||||
@ -2023,13 +2023,10 @@ func setupRootlessSpecChanges(spec *specs.Spec, bundleDir string, shmSize string
|
|||||||
Options: []string{bind.NoBindOption, "rbind", "private", "nodev", "noexec", "nosuid", "ro"},
|
Options: []string{bind.NoBindOption, "rbind", "private", "nodev", "noexec", "nosuid", "ro"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Cover up /sys/fs/cgroup and /sys/fs/selinux, if they exist in our source for /sys.
|
// Cover up /sys/fs/cgroup, if it exist in our source for /sys.
|
||||||
if _, err := os.Stat("/sys/fs/cgroup"); err == nil {
|
if _, err := os.Stat("/sys/fs/cgroup"); err == nil {
|
||||||
spec.Linux.MaskedPaths = append(spec.Linux.MaskedPaths, "/sys/fs/cgroup")
|
spec.Linux.MaskedPaths = append(spec.Linux.MaskedPaths, "/sys/fs/cgroup")
|
||||||
}
|
}
|
||||||
if _, err := os.Stat("/sys/fs/selinux"); err == nil {
|
|
||||||
spec.Linux.MaskedPaths = append(spec.Linux.MaskedPaths, "/sys/fs/selinux")
|
|
||||||
}
|
|
||||||
// Keep anything that isn't under /dev, /proc, or /sys.
|
// Keep anything that isn't under /dev, /proc, or /sys.
|
||||||
for i := range spec.Mounts {
|
for i := range spec.Mounts {
|
||||||
if spec.Mounts[i].Destination == "/dev" || strings.HasPrefix(spec.Mounts[i].Destination, "/dev/") ||
|
if spec.Mounts[i].Destination == "/dev" || strings.HasPrefix(spec.Mounts[i].Destination, "/dev/") ||
|
||||||
@ -2073,7 +2070,7 @@ func (b *Builder) runUsingRuntimeSubproc(isolation Isolation, options RunOptions
|
|||||||
if cmd.Stderr == nil {
|
if cmd.Stderr == nil {
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
}
|
}
|
||||||
cmd.Env = append(os.Environ(), fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel()))
|
cmd.Env = util.MergeEnv(os.Environ(), []string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())})
|
||||||
preader, pwriter, err := os.Pipe()
|
preader, pwriter, err := os.Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error creating configuration pipe")
|
return errors.Wrapf(err, "error creating configuration pipe")
|
||||||
|
2
vendor/github.com/containers/buildah/troubleshooting.md
generated
vendored
2
vendor/github.com/containers/buildah/troubleshooting.md
generated
vendored
@ -76,7 +76,7 @@ the `buildah run` command will not complete and an error will be raised.
|
|||||||
|
|
||||||
#### Solution
|
#### Solution
|
||||||
There are two solutions to this problem. The
|
There are two solutions to this problem. The
|
||||||
[`podman run`](https://github.com/containers/libpod/blob/master/docs/podman-run.1.md)
|
[`podman run`](https://github.com/containers/podman/blob/master/docs/podman-run.1.md)
|
||||||
command can be used in place of `buildah run`. To still use `buildah run`, surround
|
command can be used in place of `buildah run`. To still use `buildah run`, surround
|
||||||
the command with single quotes and use `bash -c`. The previous examples would be
|
the command with single quotes and use `bash -c`. The previous examples would be
|
||||||
changed to:
|
changed to:
|
||||||
|
16
vendor/github.com/containers/buildah/util/util.go
generated
vendored
16
vendor/github.com/containers/buildah/util/util.go
generated
vendored
@ -469,3 +469,19 @@ func FindLocalRuntime(runtime string) string {
|
|||||||
}
|
}
|
||||||
return localRuntime
|
return localRuntime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MergeEnv merges two lists of environment variables, avoiding duplicates.
|
||||||
|
func MergeEnv(defaults, overrides []string) []string {
|
||||||
|
s := make([]string, 0, len(defaults)+len(overrides))
|
||||||
|
index := make(map[string]int)
|
||||||
|
for _, envSpec := range append(defaults, overrides...) {
|
||||||
|
envVar := strings.SplitN(envSpec, "=", 2)
|
||||||
|
if i, ok := index[envVar[0]]; ok {
|
||||||
|
s[i] = envSpec
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s = append(s, envSpec)
|
||||||
|
index[envVar[0]] = len(s) - 1
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
22
vendor/github.com/containers/ocicrypt/.travis.yml
generated
vendored
Normal file
22
vendor/github.com/containers/ocicrypt/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
dist: xenial
|
||||||
|
language: go
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
|
||||||
|
go:
|
||||||
|
- "1.13.x"
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
|
||||||
|
go_import_path: github.com/containers/ocicrypt
|
||||||
|
|
||||||
|
install:
|
||||||
|
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.19.1
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make
|
||||||
|
- make check
|
||||||
|
- make test
|
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/master/SECURITY.md) for the Containers Projects.
|
8
vendor/github.com/containers/ocicrypt/go.mod
generated
vendored
8
vendor/github.com/containers/ocicrypt/go.mod
generated
vendored
@ -3,15 +3,13 @@ module github.com/containers/ocicrypt
|
|||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/containerd/containerd v1.2.10
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa
|
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1
|
github.com/opencontainers/go-digest v1.0.0-rc1
|
||||||
github.com/opencontainers/image-spec v1.0.1
|
github.com/opencontainers/image-spec v1.0.1
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/sirupsen/logrus v1.4.2 // indirect
|
|
||||||
github.com/stretchr/testify v1.3.0 // indirect
|
github.com/stretchr/testify v1.3.0 // indirect
|
||||||
|
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||||
google.golang.org/grpc v1.24.0 // indirect
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.3.1
|
gopkg.in/square/go-jose.v2 v2.3.1
|
||||||
gotest.tools v2.2.0+incompatible // indirect
|
|
||||||
)
|
)
|
||||||
|
36
vendor/github.com/containers/ocicrypt/go.sum
generated
vendored
36
vendor/github.com/containers/ocicrypt/go.sum
generated
vendored
@ -1,23 +1,7 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/containerd/containerd v1.2.10 h1:liQDhXqIn7y6cJ/7qBgOaZsiTZJc56/wkkhDBiDBRDw=
|
|
||||||
github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=
|
|
||||||
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||||
@ -26,22 +10,16 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
|||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
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=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -49,15 +27,5 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/p
|
|||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s=
|
|
||||||
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
|
|
||||||
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
|
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
|
||||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
|
4
vendor/github.com/containers/ocicrypt/gpg.go
generated
vendored
4
vendor/github.com/containers/ocicrypt/gpg.go
generated
vendored
@ -170,7 +170,7 @@ func (gc *gpgv2Client) getKeyDetails(option string, keyid uint64) ([]byte, bool,
|
|||||||
var args []string
|
var args []string
|
||||||
|
|
||||||
if gc.gpgHomeDir != "" {
|
if gc.gpgHomeDir != "" {
|
||||||
args = append([]string{"--homedir", gc.gpgHomeDir})
|
args = []string{"--homedir", gc.gpgHomeDir}
|
||||||
}
|
}
|
||||||
args = append(args, option, fmt.Sprintf("0x%x", keyid))
|
args = append(args, option, fmt.Sprintf("0x%x", keyid))
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ func (gc *gpgv1Client) getKeyDetails(option string, keyid uint64) ([]byte, bool,
|
|||||||
var args []string
|
var args []string
|
||||||
|
|
||||||
if gc.gpgHomeDir != "" {
|
if gc.gpgHomeDir != "" {
|
||||||
args = append([]string{"--homedir", gc.gpgHomeDir})
|
args = []string{"--homedir", gc.gpgHomeDir}
|
||||||
}
|
}
|
||||||
args = append(args, option, fmt.Sprintf("0x%x", keyid))
|
args = append(args, option, fmt.Sprintf("0x%x", keyid))
|
||||||
|
|
||||||
|
2
vendor/github.com/containers/ocicrypt/keywrap/pkcs7/keywrapper_pkcs7.go
generated
vendored
2
vendor/github.com/containers/ocicrypt/keywrap/pkcs7/keywrapper_pkcs7.go
generated
vendored
@ -23,8 +23,8 @@ import (
|
|||||||
"github.com/containers/ocicrypt/config"
|
"github.com/containers/ocicrypt/config"
|
||||||
"github.com/containers/ocicrypt/keywrap"
|
"github.com/containers/ocicrypt/keywrap"
|
||||||
"github.com/containers/ocicrypt/utils"
|
"github.com/containers/ocicrypt/utils"
|
||||||
"github.com/fullsailor/pkcs7"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"go.mozilla.org/pkcs7"
|
||||||
)
|
)
|
||||||
|
|
||||||
type pkcs7KeyWrapper struct {
|
type pkcs7KeyWrapper struct {
|
||||||
|
7
vendor/github.com/fullsailor/pkcs7/.travis.yml
generated
vendored
7
vendor/github.com/fullsailor/pkcs7/.travis.yml
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.8
|
|
||||||
- 1.9
|
|
||||||
- "1.10"
|
|
||||||
- tip
|
|
8
vendor/github.com/fullsailor/pkcs7/README.md
generated
vendored
8
vendor/github.com/fullsailor/pkcs7/README.md
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
# pkcs7
|
|
||||||
|
|
||||||
[](https://godoc.org/github.com/fullsailor/pkcs7)
|
|
||||||
[](https://travis-ci.org/fullsailor/pkcs7)
|
|
||||||
|
|
||||||
pkcs7 implements parsing and creating signed and enveloped messages.
|
|
||||||
|
|
||||||
- Documentation on [GoDoc](http://godoc.org/github.com/fullsailor/pkcs7)
|
|
962
vendor/github.com/fullsailor/pkcs7/pkcs7.go
generated
vendored
962
vendor/github.com/fullsailor/pkcs7/pkcs7.go
generated
vendored
@ -1,962 +0,0 @@
|
|||||||
// Package pkcs7 implements parsing and generation of some PKCS#7 structures.
|
|
||||||
package pkcs7
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/des"
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/x509"
|
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/asn1"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"math/big"
|
|
||||||
"sort"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
_ "crypto/sha1" // for crypto.SHA1
|
|
||||||
)
|
|
||||||
|
|
||||||
// PKCS7 Represents a PKCS7 structure
|
|
||||||
type PKCS7 struct {
|
|
||||||
Content []byte
|
|
||||||
Certificates []*x509.Certificate
|
|
||||||
CRLs []pkix.CertificateList
|
|
||||||
Signers []signerInfo
|
|
||||||
raw interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type contentInfo struct {
|
|
||||||
ContentType asn1.ObjectIdentifier
|
|
||||||
Content asn1.RawValue `asn1:"explicit,optional,tag:0"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrUnsupportedContentType is returned when a PKCS7 content is not supported.
|
|
||||||
// Currently only Data (1.2.840.113549.1.7.1), Signed Data (1.2.840.113549.1.7.2),
|
|
||||||
// and Enveloped Data are supported (1.2.840.113549.1.7.3)
|
|
||||||
var ErrUnsupportedContentType = errors.New("pkcs7: cannot parse data: unimplemented content type")
|
|
||||||
|
|
||||||
type unsignedData []byte
|
|
||||||
|
|
||||||
var (
|
|
||||||
oidData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1}
|
|
||||||
oidSignedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2}
|
|
||||||
oidEnvelopedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 3}
|
|
||||||
oidSignedAndEnvelopedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 4}
|
|
||||||
oidDigestedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 5}
|
|
||||||
oidEncryptedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 6}
|
|
||||||
oidAttributeContentType = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 3}
|
|
||||||
oidAttributeMessageDigest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 4}
|
|
||||||
oidAttributeSigningTime = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 5}
|
|
||||||
)
|
|
||||||
|
|
||||||
type signedData struct {
|
|
||||||
Version int `asn1:"default:1"`
|
|
||||||
DigestAlgorithmIdentifiers []pkix.AlgorithmIdentifier `asn1:"set"`
|
|
||||||
ContentInfo contentInfo
|
|
||||||
Certificates rawCertificates `asn1:"optional,tag:0"`
|
|
||||||
CRLs []pkix.CertificateList `asn1:"optional,tag:1"`
|
|
||||||
SignerInfos []signerInfo `asn1:"set"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type rawCertificates struct {
|
|
||||||
Raw asn1.RawContent
|
|
||||||
}
|
|
||||||
|
|
||||||
type envelopedData struct {
|
|
||||||
Version int
|
|
||||||
RecipientInfos []recipientInfo `asn1:"set"`
|
|
||||||
EncryptedContentInfo encryptedContentInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
type recipientInfo struct {
|
|
||||||
Version int
|
|
||||||
IssuerAndSerialNumber issuerAndSerial
|
|
||||||
KeyEncryptionAlgorithm pkix.AlgorithmIdentifier
|
|
||||||
EncryptedKey []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type encryptedContentInfo struct {
|
|
||||||
ContentType asn1.ObjectIdentifier
|
|
||||||
ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
|
|
||||||
EncryptedContent asn1.RawValue `asn1:"tag:0,optional"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type attribute struct {
|
|
||||||
Type asn1.ObjectIdentifier
|
|
||||||
Value asn1.RawValue `asn1:"set"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type issuerAndSerial struct {
|
|
||||||
IssuerName asn1.RawValue
|
|
||||||
SerialNumber *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
// MessageDigestMismatchError is returned when the signer data digest does not
|
|
||||||
// match the computed digest for the contained content
|
|
||||||
type MessageDigestMismatchError struct {
|
|
||||||
ExpectedDigest []byte
|
|
||||||
ActualDigest []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err *MessageDigestMismatchError) Error() string {
|
|
||||||
return fmt.Sprintf("pkcs7: Message digest mismatch\n\tExpected: %X\n\tActual : %X", err.ExpectedDigest, err.ActualDigest)
|
|
||||||
}
|
|
||||||
|
|
||||||
type signerInfo struct {
|
|
||||||
Version int `asn1:"default:1"`
|
|
||||||
IssuerAndSerialNumber issuerAndSerial
|
|
||||||
DigestAlgorithm pkix.AlgorithmIdentifier
|
|
||||||
AuthenticatedAttributes []attribute `asn1:"optional,tag:0"`
|
|
||||||
DigestEncryptionAlgorithm pkix.AlgorithmIdentifier
|
|
||||||
EncryptedDigest []byte
|
|
||||||
UnauthenticatedAttributes []attribute `asn1:"optional,tag:1"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse decodes a DER encoded PKCS7 package
|
|
||||||
func Parse(data []byte) (p7 *PKCS7, err error) {
|
|
||||||
if len(data) == 0 {
|
|
||||||
return nil, errors.New("pkcs7: input data is empty")
|
|
||||||
}
|
|
||||||
var info contentInfo
|
|
||||||
der, err := ber2der(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rest, err := asn1.Unmarshal(der, &info)
|
|
||||||
if len(rest) > 0 {
|
|
||||||
err = asn1.SyntaxError{Msg: "trailing data"}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmt.Printf("--> Content Type: %s", info.ContentType)
|
|
||||||
switch {
|
|
||||||
case info.ContentType.Equal(oidSignedData):
|
|
||||||
return parseSignedData(info.Content.Bytes)
|
|
||||||
case info.ContentType.Equal(oidEnvelopedData):
|
|
||||||
return parseEnvelopedData(info.Content.Bytes)
|
|
||||||
}
|
|
||||||
return nil, ErrUnsupportedContentType
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseSignedData(data []byte) (*PKCS7, error) {
|
|
||||||
var sd signedData
|
|
||||||
asn1.Unmarshal(data, &sd)
|
|
||||||
certs, err := sd.Certificates.Parse()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// fmt.Printf("--> Signed Data Version %d\n", sd.Version)
|
|
||||||
|
|
||||||
var compound asn1.RawValue
|
|
||||||
var content unsignedData
|
|
||||||
|
|
||||||
// The Content.Bytes maybe empty on PKI responses.
|
|
||||||
if len(sd.ContentInfo.Content.Bytes) > 0 {
|
|
||||||
if _, err := asn1.Unmarshal(sd.ContentInfo.Content.Bytes, &compound); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Compound octet string
|
|
||||||
if compound.IsCompound {
|
|
||||||
if _, err = asn1.Unmarshal(compound.Bytes, &content); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// assuming this is tag 04
|
|
||||||
content = compound.Bytes
|
|
||||||
}
|
|
||||||
return &PKCS7{
|
|
||||||
Content: content,
|
|
||||||
Certificates: certs,
|
|
||||||
CRLs: sd.CRLs,
|
|
||||||
Signers: sd.SignerInfos,
|
|
||||||
raw: sd}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (raw rawCertificates) Parse() ([]*x509.Certificate, error) {
|
|
||||||
if len(raw.Raw) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var val asn1.RawValue
|
|
||||||
if _, err := asn1.Unmarshal(raw.Raw, &val); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return x509.ParseCertificates(val.Bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseEnvelopedData(data []byte) (*PKCS7, error) {
|
|
||||||
var ed envelopedData
|
|
||||||
if _, err := asn1.Unmarshal(data, &ed); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &PKCS7{
|
|
||||||
raw: ed,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify checks the signatures of a PKCS7 object
|
|
||||||
// WARNING: Verify does not check signing time or verify certificate chains at
|
|
||||||
// this time.
|
|
||||||
func (p7 *PKCS7) Verify() (err error) {
|
|
||||||
if len(p7.Signers) == 0 {
|
|
||||||
return errors.New("pkcs7: Message has no signers")
|
|
||||||
}
|
|
||||||
for _, signer := range p7.Signers {
|
|
||||||
if err := verifySignature(p7, signer); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifySignature(p7 *PKCS7, signer signerInfo) error {
|
|
||||||
signedData := p7.Content
|
|
||||||
hash, err := getHashForOID(signer.DigestAlgorithm.Algorithm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(signer.AuthenticatedAttributes) > 0 {
|
|
||||||
// TODO(fullsailor): First check the content type match
|
|
||||||
var digest []byte
|
|
||||||
err := unmarshalAttribute(signer.AuthenticatedAttributes, oidAttributeMessageDigest, &digest)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h := hash.New()
|
|
||||||
h.Write(p7.Content)
|
|
||||||
computed := h.Sum(nil)
|
|
||||||
if !hmac.Equal(digest, computed) {
|
|
||||||
return &MessageDigestMismatchError{
|
|
||||||
ExpectedDigest: digest,
|
|
||||||
ActualDigest: computed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO(fullsailor): Optionally verify certificate chain
|
|
||||||
// TODO(fullsailor): Optionally verify signingTime against certificate NotAfter/NotBefore
|
|
||||||
signedData, err = marshalAttributes(signer.AuthenticatedAttributes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cert := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
|
|
||||||
if cert == nil {
|
|
||||||
return errors.New("pkcs7: No certificate for signer")
|
|
||||||
}
|
|
||||||
|
|
||||||
algo := getSignatureAlgorithmFromAI(signer.DigestEncryptionAlgorithm)
|
|
||||||
if algo == x509.UnknownSignatureAlgorithm {
|
|
||||||
// I'm not sure what the spec here is, and the openssl sources were not
|
|
||||||
// helpful. But, this is what App Store receipts appear to do.
|
|
||||||
// The DigestEncryptionAlgorithm is just "rsaEncryption (PKCS #1)"
|
|
||||||
// But we're expecting a digest + encryption algorithm. So... we're going
|
|
||||||
// to determine an algorithm based on the DigestAlgorithm and this
|
|
||||||
// encryption algorithm.
|
|
||||||
if signer.DigestEncryptionAlgorithm.Algorithm.Equal(oidEncryptionAlgorithmRSA) {
|
|
||||||
algo = getRSASignatureAlgorithmForDigestAlgorithm(hash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cert.CheckSignature(algo, signedData, signer.EncryptedDigest)
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalAttributes(attrs []attribute) ([]byte, error) {
|
|
||||||
encodedAttributes, err := asn1.Marshal(struct {
|
|
||||||
A []attribute `asn1:"set"`
|
|
||||||
}{A: attrs})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the leading sequence octets
|
|
||||||
var raw asn1.RawValue
|
|
||||||
asn1.Unmarshal(encodedAttributes, &raw)
|
|
||||||
return raw.Bytes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
oidDigestAlgorithmSHA1 = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26}
|
|
||||||
oidEncryptionAlgorithmRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
|
|
||||||
)
|
|
||||||
|
|
||||||
func getCertFromCertsByIssuerAndSerial(certs []*x509.Certificate, ias issuerAndSerial) *x509.Certificate {
|
|
||||||
for _, cert := range certs {
|
|
||||||
if isCertMatchForIssuerAndSerial(cert, ias) {
|
|
||||||
return cert
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getHashForOID(oid asn1.ObjectIdentifier) (crypto.Hash, error) {
|
|
||||||
switch {
|
|
||||||
case oid.Equal(oidDigestAlgorithmSHA1):
|
|
||||||
return crypto.SHA1, nil
|
|
||||||
case oid.Equal(oidSHA256):
|
|
||||||
return crypto.SHA256, nil
|
|
||||||
}
|
|
||||||
return crypto.Hash(0), ErrUnsupportedAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRSASignatureAlgorithmForDigestAlgorithm(hash crypto.Hash) x509.SignatureAlgorithm {
|
|
||||||
for _, details := range signatureAlgorithmDetails {
|
|
||||||
if details.pubKeyAlgo == x509.RSA && details.hash == hash {
|
|
||||||
return details.algo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return x509.UnknownSignatureAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOnlySigner returns an x509.Certificate for the first signer of the signed
|
|
||||||
// data payload. If there are more or less than one signer, nil is returned
|
|
||||||
func (p7 *PKCS7) GetOnlySigner() *x509.Certificate {
|
|
||||||
if len(p7.Signers) != 1 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
signer := p7.Signers[0]
|
|
||||||
return getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrUnsupportedAlgorithm tells you when our quick dev assumptions have failed
|
|
||||||
var ErrUnsupportedAlgorithm = errors.New("pkcs7: cannot decrypt data: only RSA, DES, DES-EDE3, AES-256-CBC and AES-128-GCM supported")
|
|
||||||
|
|
||||||
// ErrNotEncryptedContent is returned when attempting to Decrypt data that is not encrypted data
|
|
||||||
var ErrNotEncryptedContent = errors.New("pkcs7: content data is a decryptable data type")
|
|
||||||
|
|
||||||
// Decrypt decrypts encrypted content info for recipient cert and private key
|
|
||||||
func (p7 *PKCS7) Decrypt(cert *x509.Certificate, pk crypto.PrivateKey) ([]byte, error) {
|
|
||||||
data, ok := p7.raw.(envelopedData)
|
|
||||||
if !ok {
|
|
||||||
return nil, ErrNotEncryptedContent
|
|
||||||
}
|
|
||||||
recipient := selectRecipientForCertificate(data.RecipientInfos, cert)
|
|
||||||
if recipient.EncryptedKey == nil {
|
|
||||||
return nil, errors.New("pkcs7: no enveloped recipient for provided certificate")
|
|
||||||
}
|
|
||||||
if priv := pk.(*rsa.PrivateKey); priv != nil {
|
|
||||||
var contentKey []byte
|
|
||||||
contentKey, err := rsa.DecryptPKCS1v15(rand.Reader, priv, recipient.EncryptedKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return data.EncryptedContentInfo.decrypt(contentKey)
|
|
||||||
}
|
|
||||||
fmt.Printf("Unsupported Private Key: %v\n", pk)
|
|
||||||
return nil, ErrUnsupportedAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
var oidEncryptionAlgorithmDESCBC = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7}
|
|
||||||
var oidEncryptionAlgorithmDESEDE3CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7}
|
|
||||||
var oidEncryptionAlgorithmAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42}
|
|
||||||
var oidEncryptionAlgorithmAES128GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 6}
|
|
||||||
var oidEncryptionAlgorithmAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}
|
|
||||||
|
|
||||||
func (eci encryptedContentInfo) decrypt(key []byte) ([]byte, error) {
|
|
||||||
alg := eci.ContentEncryptionAlgorithm.Algorithm
|
|
||||||
if !alg.Equal(oidEncryptionAlgorithmDESCBC) &&
|
|
||||||
!alg.Equal(oidEncryptionAlgorithmDESEDE3CBC) &&
|
|
||||||
!alg.Equal(oidEncryptionAlgorithmAES256CBC) &&
|
|
||||||
!alg.Equal(oidEncryptionAlgorithmAES128CBC) &&
|
|
||||||
!alg.Equal(oidEncryptionAlgorithmAES128GCM) {
|
|
||||||
fmt.Printf("Unsupported Content Encryption Algorithm: %s\n", alg)
|
|
||||||
return nil, ErrUnsupportedAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncryptedContent can either be constructed of multple OCTET STRINGs
|
|
||||||
// or _be_ a tagged OCTET STRING
|
|
||||||
var cyphertext []byte
|
|
||||||
if eci.EncryptedContent.IsCompound {
|
|
||||||
// Complex case to concat all of the children OCTET STRINGs
|
|
||||||
var buf bytes.Buffer
|
|
||||||
cypherbytes := eci.EncryptedContent.Bytes
|
|
||||||
for {
|
|
||||||
var part []byte
|
|
||||||
cypherbytes, _ = asn1.Unmarshal(cypherbytes, &part)
|
|
||||||
buf.Write(part)
|
|
||||||
if cypherbytes == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cyphertext = buf.Bytes()
|
|
||||||
} else {
|
|
||||||
// Simple case, the bytes _are_ the cyphertext
|
|
||||||
cyphertext = eci.EncryptedContent.Bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
var block cipher.Block
|
|
||||||
var err error
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case alg.Equal(oidEncryptionAlgorithmDESCBC):
|
|
||||||
block, err = des.NewCipher(key)
|
|
||||||
case alg.Equal(oidEncryptionAlgorithmDESEDE3CBC):
|
|
||||||
block, err = des.NewTripleDESCipher(key)
|
|
||||||
case alg.Equal(oidEncryptionAlgorithmAES256CBC):
|
|
||||||
fallthrough
|
|
||||||
case alg.Equal(oidEncryptionAlgorithmAES128GCM), alg.Equal(oidEncryptionAlgorithmAES128CBC):
|
|
||||||
block, err = aes.NewCipher(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if alg.Equal(oidEncryptionAlgorithmAES128GCM) {
|
|
||||||
params := aesGCMParameters{}
|
|
||||||
paramBytes := eci.ContentEncryptionAlgorithm.Parameters.Bytes
|
|
||||||
|
|
||||||
_, err := asn1.Unmarshal(paramBytes, ¶ms)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
gcm, err := cipher.NewGCM(block)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(params.Nonce) != gcm.NonceSize() {
|
|
||||||
return nil, errors.New("pkcs7: encryption algorithm parameters are incorrect")
|
|
||||||
}
|
|
||||||
if params.ICVLen != gcm.Overhead() {
|
|
||||||
return nil, errors.New("pkcs7: encryption algorithm parameters are incorrect")
|
|
||||||
}
|
|
||||||
|
|
||||||
plaintext, err := gcm.Open(nil, params.Nonce, cyphertext, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return plaintext, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
iv := eci.ContentEncryptionAlgorithm.Parameters.Bytes
|
|
||||||
if len(iv) != block.BlockSize() {
|
|
||||||
return nil, errors.New("pkcs7: encryption algorithm parameters are malformed")
|
|
||||||
}
|
|
||||||
mode := cipher.NewCBCDecrypter(block, iv)
|
|
||||||
plaintext := make([]byte, len(cyphertext))
|
|
||||||
mode.CryptBlocks(plaintext, cyphertext)
|
|
||||||
if plaintext, err = unpad(plaintext, mode.BlockSize()); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return plaintext, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func selectRecipientForCertificate(recipients []recipientInfo, cert *x509.Certificate) recipientInfo {
|
|
||||||
for _, recp := range recipients {
|
|
||||||
if isCertMatchForIssuerAndSerial(cert, recp.IssuerAndSerialNumber) {
|
|
||||||
return recp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return recipientInfo{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isCertMatchForIssuerAndSerial(cert *x509.Certificate, ias issuerAndSerial) bool {
|
|
||||||
return cert.SerialNumber.Cmp(ias.SerialNumber) == 0 && bytes.Compare(cert.RawIssuer, ias.IssuerName.FullBytes) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func pad(data []byte, blocklen int) ([]byte, error) {
|
|
||||||
if blocklen < 1 {
|
|
||||||
return nil, fmt.Errorf("invalid blocklen %d", blocklen)
|
|
||||||
}
|
|
||||||
padlen := blocklen - (len(data) % blocklen)
|
|
||||||
if padlen == 0 {
|
|
||||||
padlen = blocklen
|
|
||||||
}
|
|
||||||
pad := bytes.Repeat([]byte{byte(padlen)}, padlen)
|
|
||||||
return append(data, pad...), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func unpad(data []byte, blocklen int) ([]byte, error) {
|
|
||||||
if blocklen < 1 {
|
|
||||||
return nil, fmt.Errorf("invalid blocklen %d", blocklen)
|
|
||||||
}
|
|
||||||
if len(data)%blocklen != 0 || len(data) == 0 {
|
|
||||||
return nil, fmt.Errorf("invalid data len %d", len(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// the last byte is the length of padding
|
|
||||||
padlen := int(data[len(data)-1])
|
|
||||||
|
|
||||||
// check padding integrity, all bytes should be the same
|
|
||||||
pad := data[len(data)-padlen:]
|
|
||||||
for _, padbyte := range pad {
|
|
||||||
if padbyte != byte(padlen) {
|
|
||||||
return nil, errors.New("invalid padding")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return data[:len(data)-padlen], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func unmarshalAttribute(attrs []attribute, attributeType asn1.ObjectIdentifier, out interface{}) error {
|
|
||||||
for _, attr := range attrs {
|
|
||||||
if attr.Type.Equal(attributeType) {
|
|
||||||
_, err := asn1.Unmarshal(attr.Value.Bytes, out)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errors.New("pkcs7: attribute type not in attributes")
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalSignedAttribute decodes a single attribute from the signer info
|
|
||||||
func (p7 *PKCS7) UnmarshalSignedAttribute(attributeType asn1.ObjectIdentifier, out interface{}) error {
|
|
||||||
sd, ok := p7.raw.(signedData)
|
|
||||||
if !ok {
|
|
||||||
return errors.New("pkcs7: payload is not signedData content")
|
|
||||||
}
|
|
||||||
if len(sd.SignerInfos) < 1 {
|
|
||||||
return errors.New("pkcs7: payload has no signers")
|
|
||||||
}
|
|
||||||
attributes := sd.SignerInfos[0].AuthenticatedAttributes
|
|
||||||
return unmarshalAttribute(attributes, attributeType, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignedData is an opaque data structure for creating signed data payloads
|
|
||||||
type SignedData struct {
|
|
||||||
sd signedData
|
|
||||||
certs []*x509.Certificate
|
|
||||||
messageDigest []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attribute represents a key value pair attribute. Value must be marshalable byte
|
|
||||||
// `encoding/asn1`
|
|
||||||
type Attribute struct {
|
|
||||||
Type asn1.ObjectIdentifier
|
|
||||||
Value interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignerInfoConfig are optional values to include when adding a signer
|
|
||||||
type SignerInfoConfig struct {
|
|
||||||
ExtraSignedAttributes []Attribute
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSignedData initializes a SignedData with content
|
|
||||||
func NewSignedData(data []byte) (*SignedData, error) {
|
|
||||||
content, err := asn1.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ci := contentInfo{
|
|
||||||
ContentType: oidData,
|
|
||||||
Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true},
|
|
||||||
}
|
|
||||||
digAlg := pkix.AlgorithmIdentifier{
|
|
||||||
Algorithm: oidDigestAlgorithmSHA1,
|
|
||||||
}
|
|
||||||
h := crypto.SHA1.New()
|
|
||||||
h.Write(data)
|
|
||||||
md := h.Sum(nil)
|
|
||||||
sd := signedData{
|
|
||||||
ContentInfo: ci,
|
|
||||||
Version: 1,
|
|
||||||
DigestAlgorithmIdentifiers: []pkix.AlgorithmIdentifier{digAlg},
|
|
||||||
}
|
|
||||||
return &SignedData{sd: sd, messageDigest: md}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type attributes struct {
|
|
||||||
types []asn1.ObjectIdentifier
|
|
||||||
values []interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add adds the attribute, maintaining insertion order
|
|
||||||
func (attrs *attributes) Add(attrType asn1.ObjectIdentifier, value interface{}) {
|
|
||||||
attrs.types = append(attrs.types, attrType)
|
|
||||||
attrs.values = append(attrs.values, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
type sortableAttribute struct {
|
|
||||||
SortKey []byte
|
|
||||||
Attribute attribute
|
|
||||||
}
|
|
||||||
|
|
||||||
type attributeSet []sortableAttribute
|
|
||||||
|
|
||||||
func (sa attributeSet) Len() int {
|
|
||||||
return len(sa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sa attributeSet) Less(i, j int) bool {
|
|
||||||
return bytes.Compare(sa[i].SortKey, sa[j].SortKey) < 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sa attributeSet) Swap(i, j int) {
|
|
||||||
sa[i], sa[j] = sa[j], sa[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sa attributeSet) Attributes() []attribute {
|
|
||||||
attrs := make([]attribute, len(sa))
|
|
||||||
for i, attr := range sa {
|
|
||||||
attrs[i] = attr.Attribute
|
|
||||||
}
|
|
||||||
return attrs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (attrs *attributes) ForMarshaling() ([]attribute, error) {
|
|
||||||
sortables := make(attributeSet, len(attrs.types))
|
|
||||||
for i := range sortables {
|
|
||||||
attrType := attrs.types[i]
|
|
||||||
attrValue := attrs.values[i]
|
|
||||||
asn1Value, err := asn1.Marshal(attrValue)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
attr := attribute{
|
|
||||||
Type: attrType,
|
|
||||||
Value: asn1.RawValue{Tag: 17, IsCompound: true, Bytes: asn1Value}, // 17 == SET tag
|
|
||||||
}
|
|
||||||
encoded, err := asn1.Marshal(attr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sortables[i] = sortableAttribute{
|
|
||||||
SortKey: encoded,
|
|
||||||
Attribute: attr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Sort(sortables)
|
|
||||||
return sortables.Attributes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddSigner signs attributes about the content and adds certificate to payload
|
|
||||||
func (sd *SignedData) AddSigner(cert *x509.Certificate, pkey crypto.PrivateKey, config SignerInfoConfig) error {
|
|
||||||
attrs := &attributes{}
|
|
||||||
attrs.Add(oidAttributeContentType, sd.sd.ContentInfo.ContentType)
|
|
||||||
attrs.Add(oidAttributeMessageDigest, sd.messageDigest)
|
|
||||||
attrs.Add(oidAttributeSigningTime, time.Now())
|
|
||||||
for _, attr := range config.ExtraSignedAttributes {
|
|
||||||
attrs.Add(attr.Type, attr.Value)
|
|
||||||
}
|
|
||||||
finalAttrs, err := attrs.ForMarshaling()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
signature, err := signAttributes(finalAttrs, pkey, crypto.SHA1)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ias, err := cert2issuerAndSerial(cert)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
signer := signerInfo{
|
|
||||||
AuthenticatedAttributes: finalAttrs,
|
|
||||||
DigestAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidDigestAlgorithmSHA1},
|
|
||||||
DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSignatureSHA1WithRSA},
|
|
||||||
IssuerAndSerialNumber: ias,
|
|
||||||
EncryptedDigest: signature,
|
|
||||||
Version: 1,
|
|
||||||
}
|
|
||||||
// create signature of signed attributes
|
|
||||||
sd.certs = append(sd.certs, cert)
|
|
||||||
sd.sd.SignerInfos = append(sd.sd.SignerInfos, signer)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddCertificate adds the certificate to the payload. Useful for parent certificates
|
|
||||||
func (sd *SignedData) AddCertificate(cert *x509.Certificate) {
|
|
||||||
sd.certs = append(sd.certs, cert)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detach removes content from the signed data struct to make it a detached signature.
|
|
||||||
// This must be called right before Finish()
|
|
||||||
func (sd *SignedData) Detach() {
|
|
||||||
sd.sd.ContentInfo = contentInfo{ContentType: oidData}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish marshals the content and its signers
|
|
||||||
func (sd *SignedData) Finish() ([]byte, error) {
|
|
||||||
sd.sd.Certificates = marshalCertificates(sd.certs)
|
|
||||||
inner, err := asn1.Marshal(sd.sd)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
outer := contentInfo{
|
|
||||||
ContentType: oidSignedData,
|
|
||||||
Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: inner, IsCompound: true},
|
|
||||||
}
|
|
||||||
return asn1.Marshal(outer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cert2issuerAndSerial(cert *x509.Certificate) (issuerAndSerial, error) {
|
|
||||||
var ias issuerAndSerial
|
|
||||||
// The issuer RDNSequence has to match exactly the sequence in the certificate
|
|
||||||
// We cannot use cert.Issuer.ToRDNSequence() here since it mangles the sequence
|
|
||||||
ias.IssuerName = asn1.RawValue{FullBytes: cert.RawIssuer}
|
|
||||||
ias.SerialNumber = cert.SerialNumber
|
|
||||||
|
|
||||||
return ias, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// signs the DER encoded form of the attributes with the private key
|
|
||||||
func signAttributes(attrs []attribute, pkey crypto.PrivateKey, hash crypto.Hash) ([]byte, error) {
|
|
||||||
attrBytes, err := marshalAttributes(attrs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
h := hash.New()
|
|
||||||
h.Write(attrBytes)
|
|
||||||
hashed := h.Sum(nil)
|
|
||||||
switch priv := pkey.(type) {
|
|
||||||
case *rsa.PrivateKey:
|
|
||||||
return rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA1, hashed)
|
|
||||||
}
|
|
||||||
return nil, ErrUnsupportedAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
// concats and wraps the certificates in the RawValue structure
|
|
||||||
func marshalCertificates(certs []*x509.Certificate) rawCertificates {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for _, cert := range certs {
|
|
||||||
buf.Write(cert.Raw)
|
|
||||||
}
|
|
||||||
rawCerts, _ := marshalCertificateBytes(buf.Bytes())
|
|
||||||
return rawCerts
|
|
||||||
}
|
|
||||||
|
|
||||||
// Even though, the tag & length are stripped out during marshalling the
|
|
||||||
// RawContent, we have to encode it into the RawContent. If its missing,
|
|
||||||
// then `asn1.Marshal()` will strip out the certificate wrapper instead.
|
|
||||||
func marshalCertificateBytes(certs []byte) (rawCertificates, error) {
|
|
||||||
var val = asn1.RawValue{Bytes: certs, Class: 2, Tag: 0, IsCompound: true}
|
|
||||||
b, err := asn1.Marshal(val)
|
|
||||||
if err != nil {
|
|
||||||
return rawCertificates{}, err
|
|
||||||
}
|
|
||||||
return rawCertificates{Raw: b}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DegenerateCertificate creates a signed data structure containing only the
|
|
||||||
// provided certificate or certificate chain.
|
|
||||||
func DegenerateCertificate(cert []byte) ([]byte, error) {
|
|
||||||
rawCert, err := marshalCertificateBytes(cert)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
emptyContent := contentInfo{ContentType: oidData}
|
|
||||||
sd := signedData{
|
|
||||||
Version: 1,
|
|
||||||
ContentInfo: emptyContent,
|
|
||||||
Certificates: rawCert,
|
|
||||||
CRLs: []pkix.CertificateList{},
|
|
||||||
}
|
|
||||||
content, err := asn1.Marshal(sd)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
signedContent := contentInfo{
|
|
||||||
ContentType: oidSignedData,
|
|
||||||
Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true},
|
|
||||||
}
|
|
||||||
return asn1.Marshal(signedContent)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
EncryptionAlgorithmDESCBC = iota
|
|
||||||
EncryptionAlgorithmAES128GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
// ContentEncryptionAlgorithm determines the algorithm used to encrypt the
|
|
||||||
// plaintext message. Change the value of this variable to change which
|
|
||||||
// algorithm is used in the Encrypt() function.
|
|
||||||
var ContentEncryptionAlgorithm = EncryptionAlgorithmDESCBC
|
|
||||||
|
|
||||||
// ErrUnsupportedEncryptionAlgorithm is returned when attempting to encrypt
|
|
||||||
// content with an unsupported algorithm.
|
|
||||||
var ErrUnsupportedEncryptionAlgorithm = errors.New("pkcs7: cannot encrypt content: only DES-CBC and AES-128-GCM supported")
|
|
||||||
|
|
||||||
const nonceSize = 12
|
|
||||||
|
|
||||||
type aesGCMParameters struct {
|
|
||||||
Nonce []byte `asn1:"tag:4"`
|
|
||||||
ICVLen int
|
|
||||||
}
|
|
||||||
|
|
||||||
func encryptAES128GCM(content []byte) ([]byte, *encryptedContentInfo, error) {
|
|
||||||
// Create AES key and nonce
|
|
||||||
key := make([]byte, 16)
|
|
||||||
nonce := make([]byte, nonceSize)
|
|
||||||
|
|
||||||
_, err := rand.Read(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = rand.Read(nonce)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt content
|
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
gcm, err := cipher.NewGCM(block)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ciphertext := gcm.Seal(nil, nonce, content, nil)
|
|
||||||
|
|
||||||
// Prepare ASN.1 Encrypted Content Info
|
|
||||||
paramSeq := aesGCMParameters{
|
|
||||||
Nonce: nonce,
|
|
||||||
ICVLen: gcm.Overhead(),
|
|
||||||
}
|
|
||||||
|
|
||||||
paramBytes, err := asn1.Marshal(paramSeq)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
eci := encryptedContentInfo{
|
|
||||||
ContentType: oidData,
|
|
||||||
ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
|
|
||||||
Algorithm: oidEncryptionAlgorithmAES128GCM,
|
|
||||||
Parameters: asn1.RawValue{
|
|
||||||
Tag: asn1.TagSequence,
|
|
||||||
Bytes: paramBytes,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
EncryptedContent: marshalEncryptedContent(ciphertext),
|
|
||||||
}
|
|
||||||
|
|
||||||
return key, &eci, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func encryptDESCBC(content []byte) ([]byte, *encryptedContentInfo, error) {
|
|
||||||
// Create DES key & CBC IV
|
|
||||||
key := make([]byte, 8)
|
|
||||||
iv := make([]byte, des.BlockSize)
|
|
||||||
_, err := rand.Read(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
_, err = rand.Read(iv)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt padded content
|
|
||||||
block, err := des.NewCipher(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
mode := cipher.NewCBCEncrypter(block, iv)
|
|
||||||
plaintext, err := pad(content, mode.BlockSize())
|
|
||||||
cyphertext := make([]byte, len(plaintext))
|
|
||||||
mode.CryptBlocks(cyphertext, plaintext)
|
|
||||||
|
|
||||||
// Prepare ASN.1 Encrypted Content Info
|
|
||||||
eci := encryptedContentInfo{
|
|
||||||
ContentType: oidData,
|
|
||||||
ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
|
|
||||||
Algorithm: oidEncryptionAlgorithmDESCBC,
|
|
||||||
Parameters: asn1.RawValue{Tag: 4, Bytes: iv},
|
|
||||||
},
|
|
||||||
EncryptedContent: marshalEncryptedContent(cyphertext),
|
|
||||||
}
|
|
||||||
|
|
||||||
return key, &eci, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt creates and returns an envelope data PKCS7 structure with encrypted
|
|
||||||
// recipient keys for each recipient public key.
|
|
||||||
//
|
|
||||||
// The algorithm used to perform encryption is determined by the current value
|
|
||||||
// of the global ContentEncryptionAlgorithm package variable. By default, the
|
|
||||||
// value is EncryptionAlgorithmDESCBC. To use a different algorithm, change the
|
|
||||||
// value before calling Encrypt(). For example:
|
|
||||||
//
|
|
||||||
// ContentEncryptionAlgorithm = EncryptionAlgorithmAES128GCM
|
|
||||||
//
|
|
||||||
// TODO(fullsailor): Add support for encrypting content with other algorithms
|
|
||||||
func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error) {
|
|
||||||
var eci *encryptedContentInfo
|
|
||||||
var key []byte
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// Apply chosen symmetric encryption method
|
|
||||||
switch ContentEncryptionAlgorithm {
|
|
||||||
case EncryptionAlgorithmDESCBC:
|
|
||||||
key, eci, err = encryptDESCBC(content)
|
|
||||||
|
|
||||||
case EncryptionAlgorithmAES128GCM:
|
|
||||||
key, eci, err = encryptAES128GCM(content)
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, ErrUnsupportedEncryptionAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare each recipient's encrypted cipher key
|
|
||||||
recipientInfos := make([]recipientInfo, len(recipients))
|
|
||||||
for i, recipient := range recipients {
|
|
||||||
encrypted, err := encryptKey(key, recipient)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ias, err := cert2issuerAndSerial(recipient)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
info := recipientInfo{
|
|
||||||
Version: 0,
|
|
||||||
IssuerAndSerialNumber: ias,
|
|
||||||
KeyEncryptionAlgorithm: pkix.AlgorithmIdentifier{
|
|
||||||
Algorithm: oidEncryptionAlgorithmRSA,
|
|
||||||
},
|
|
||||||
EncryptedKey: encrypted,
|
|
||||||
}
|
|
||||||
recipientInfos[i] = info
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare envelope content
|
|
||||||
envelope := envelopedData{
|
|
||||||
EncryptedContentInfo: *eci,
|
|
||||||
Version: 0,
|
|
||||||
RecipientInfos: recipientInfos,
|
|
||||||
}
|
|
||||||
innerContent, err := asn1.Marshal(envelope)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare outer payload structure
|
|
||||||
wrapper := contentInfo{
|
|
||||||
ContentType: oidEnvelopedData,
|
|
||||||
Content: asn1.RawValue{Class: 2, Tag: 0, IsCompound: true, Bytes: innerContent},
|
|
||||||
}
|
|
||||||
|
|
||||||
return asn1.Marshal(wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalEncryptedContent(content []byte) asn1.RawValue {
|
|
||||||
asn1Content, _ := asn1.Marshal(content)
|
|
||||||
return asn1.RawValue{Tag: 0, Class: 2, Bytes: asn1Content, IsCompound: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
func encryptKey(key []byte, recipient *x509.Certificate) ([]byte, error) {
|
|
||||||
if pub := recipient.PublicKey.(*rsa.PublicKey); pub != nil {
|
|
||||||
return rsa.EncryptPKCS1v15(rand.Reader, pub, key)
|
|
||||||
}
|
|
||||||
return nil, ErrUnsupportedAlgorithm
|
|
||||||
}
|
|
133
vendor/github.com/fullsailor/pkcs7/x509.go
generated
vendored
133
vendor/github.com/fullsailor/pkcs7/x509.go
generated
vendored
@ -1,133 +0,0 @@
|
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the go/golang LICENSE file.
|
|
||||||
|
|
||||||
package pkcs7
|
|
||||||
|
|
||||||
// These are private constants and functions from the crypto/x509 package that
|
|
||||||
// are useful when dealing with signatures verified by x509 certificates
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
"crypto/x509"
|
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/asn1"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
|
|
||||||
oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
|
|
||||||
oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
|
|
||||||
oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
|
|
||||||
oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
|
|
||||||
oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
|
|
||||||
oidSignatureRSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10}
|
|
||||||
oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
|
|
||||||
oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
|
|
||||||
oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
|
|
||||||
oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
|
|
||||||
oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
|
|
||||||
oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
|
|
||||||
|
|
||||||
oidSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1}
|
|
||||||
oidSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2}
|
|
||||||
oidSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3}
|
|
||||||
|
|
||||||
oidMGF1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 8}
|
|
||||||
|
|
||||||
// oidISOSignatureSHA1WithRSA means the same as oidSignatureSHA1WithRSA
|
|
||||||
// but it's specified by ISO. Microsoft's makecert.exe has been known
|
|
||||||
// to produce certificates with this OID.
|
|
||||||
oidISOSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 29}
|
|
||||||
)
|
|
||||||
|
|
||||||
var signatureAlgorithmDetails = []struct {
|
|
||||||
algo x509.SignatureAlgorithm
|
|
||||||
name string
|
|
||||||
oid asn1.ObjectIdentifier
|
|
||||||
pubKeyAlgo x509.PublicKeyAlgorithm
|
|
||||||
hash crypto.Hash
|
|
||||||
}{
|
|
||||||
{x509.MD2WithRSA, "MD2-RSA", oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */},
|
|
||||||
{x509.MD5WithRSA, "MD5-RSA", oidSignatureMD5WithRSA, x509.RSA, crypto.MD5},
|
|
||||||
{x509.SHA1WithRSA, "SHA1-RSA", oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1},
|
|
||||||
{x509.SHA1WithRSA, "SHA1-RSA", oidISOSignatureSHA1WithRSA, x509.RSA, crypto.SHA1},
|
|
||||||
{x509.SHA256WithRSA, "SHA256-RSA", oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256},
|
|
||||||
{x509.SHA384WithRSA, "SHA384-RSA", oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384},
|
|
||||||
{x509.SHA512WithRSA, "SHA512-RSA", oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512},
|
|
||||||
{x509.SHA256WithRSAPSS, "SHA256-RSAPSS", oidSignatureRSAPSS, x509.RSA, crypto.SHA256},
|
|
||||||
{x509.SHA384WithRSAPSS, "SHA384-RSAPSS", oidSignatureRSAPSS, x509.RSA, crypto.SHA384},
|
|
||||||
{x509.SHA512WithRSAPSS, "SHA512-RSAPSS", oidSignatureRSAPSS, x509.RSA, crypto.SHA512},
|
|
||||||
{x509.DSAWithSHA1, "DSA-SHA1", oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1},
|
|
||||||
{x509.DSAWithSHA256, "DSA-SHA256", oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256},
|
|
||||||
{x509.ECDSAWithSHA1, "ECDSA-SHA1", oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1},
|
|
||||||
{x509.ECDSAWithSHA256, "ECDSA-SHA256", oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256},
|
|
||||||
{x509.ECDSAWithSHA384, "ECDSA-SHA384", oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384},
|
|
||||||
{x509.ECDSAWithSHA512, "ECDSA-SHA512", oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512},
|
|
||||||
}
|
|
||||||
|
|
||||||
// pssParameters reflects the parameters in an AlgorithmIdentifier that
|
|
||||||
// specifies RSA PSS. See https://tools.ietf.org/html/rfc3447#appendix-A.2.3
|
|
||||||
type pssParameters struct {
|
|
||||||
// The following three fields are not marked as
|
|
||||||
// optional because the default values specify SHA-1,
|
|
||||||
// which is no longer suitable for use in signatures.
|
|
||||||
Hash pkix.AlgorithmIdentifier `asn1:"explicit,tag:0"`
|
|
||||||
MGF pkix.AlgorithmIdentifier `asn1:"explicit,tag:1"`
|
|
||||||
SaltLength int `asn1:"explicit,tag:2"`
|
|
||||||
TrailerField int `asn1:"optional,explicit,tag:3,default:1"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// asn1.NullBytes is not available prior to Go 1.9
|
|
||||||
var nullBytes = []byte{5, 0}
|
|
||||||
|
|
||||||
func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) x509.SignatureAlgorithm {
|
|
||||||
if !ai.Algorithm.Equal(oidSignatureRSAPSS) {
|
|
||||||
for _, details := range signatureAlgorithmDetails {
|
|
||||||
if ai.Algorithm.Equal(details.oid) {
|
|
||||||
return details.algo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return x509.UnknownSignatureAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
// RSA PSS is special because it encodes important parameters
|
|
||||||
// in the Parameters.
|
|
||||||
|
|
||||||
var params pssParameters
|
|
||||||
if _, err := asn1.Unmarshal(ai.Parameters.FullBytes, ¶ms); err != nil {
|
|
||||||
return x509.UnknownSignatureAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
var mgf1HashFunc pkix.AlgorithmIdentifier
|
|
||||||
if _, err := asn1.Unmarshal(params.MGF.Parameters.FullBytes, &mgf1HashFunc); err != nil {
|
|
||||||
return x509.UnknownSignatureAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
// PSS is greatly overburdened with options. This code forces
|
|
||||||
// them into three buckets by requiring that the MGF1 hash
|
|
||||||
// function always match the message hash function (as
|
|
||||||
// recommended in
|
|
||||||
// https://tools.ietf.org/html/rfc3447#section-8.1), that the
|
|
||||||
// salt length matches the hash length, and that the trailer
|
|
||||||
// field has the default value.
|
|
||||||
if !bytes.Equal(params.Hash.Parameters.FullBytes, nullBytes) ||
|
|
||||||
!params.MGF.Algorithm.Equal(oidMGF1) ||
|
|
||||||
!mgf1HashFunc.Algorithm.Equal(params.Hash.Algorithm) ||
|
|
||||||
!bytes.Equal(mgf1HashFunc.Parameters.FullBytes, nullBytes) ||
|
|
||||||
params.TrailerField != 1 {
|
|
||||||
return x509.UnknownSignatureAlgorithm
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case params.Hash.Algorithm.Equal(oidSHA256) && params.SaltLength == 32:
|
|
||||||
return x509.SHA256WithRSAPSS
|
|
||||||
case params.Hash.Algorithm.Equal(oidSHA384) && params.SaltLength == 48:
|
|
||||||
return x509.SHA384WithRSAPSS
|
|
||||||
case params.Hash.Algorithm.Equal(oidSHA512) && params.SaltLength == 64:
|
|
||||||
return x509.SHA512WithRSAPSS
|
|
||||||
}
|
|
||||||
|
|
||||||
return x509.UnknownSignatureAlgorithm
|
|
||||||
}
|
|
10
vendor/go.mozilla.org/pkcs7/.travis.yml
generated
vendored
Normal file
10
vendor/go.mozilla.org/pkcs7/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- "1.11"
|
||||||
|
- "1.12"
|
||||||
|
- "1.13"
|
||||||
|
- tip
|
||||||
|
before_install:
|
||||||
|
- make gettools
|
||||||
|
script:
|
||||||
|
- make
|
0
vendor/github.com/fullsailor/pkcs7/LICENSE → vendor/go.mozilla.org/pkcs7/LICENSE
generated
vendored
0
vendor/github.com/fullsailor/pkcs7/LICENSE → vendor/go.mozilla.org/pkcs7/LICENSE
generated
vendored
20
vendor/go.mozilla.org/pkcs7/Makefile
generated
vendored
Normal file
20
vendor/go.mozilla.org/pkcs7/Makefile
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
all: vet staticcheck test
|
||||||
|
|
||||||
|
test:
|
||||||
|
go test -covermode=count -coverprofile=coverage.out .
|
||||||
|
|
||||||
|
showcoverage: test
|
||||||
|
go tool cover -html=coverage.out
|
||||||
|
|
||||||
|
vet:
|
||||||
|
go vet .
|
||||||
|
|
||||||
|
lint:
|
||||||
|
golint .
|
||||||
|
|
||||||
|
staticcheck:
|
||||||
|
staticcheck .
|
||||||
|
|
||||||
|
gettools:
|
||||||
|
go get -u honnef.co/go/tools/...
|
||||||
|
go get -u golang.org/x/lint/golint
|
69
vendor/go.mozilla.org/pkcs7/README.md
generated
vendored
Normal file
69
vendor/go.mozilla.org/pkcs7/README.md
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# pkcs7
|
||||||
|
|
||||||
|
[](https://godoc.org/go.mozilla.org/pkcs7)
|
||||||
|
[](https://travis-ci.org/mozilla-services/pkcs7)
|
||||||
|
|
||||||
|
pkcs7 implements parsing and creating signed and enveloped messages.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"go.mozilla.org/pkcs7"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SignAndDetach(content []byte, cert *x509.Certificate, privkey *rsa.PrivateKey) (signed []byte, err error) {
|
||||||
|
toBeSigned, err := NewSignedData(content)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Cannot initialize signed data: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = toBeSigned.AddSigner(cert, privkey, SignerInfoConfig{}); err != nil {
|
||||||
|
err = fmt.Errorf("Cannot add signer: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detach signature, omit if you want an embedded signature
|
||||||
|
toBeSigned.Detach()
|
||||||
|
|
||||||
|
signed, err = toBeSigned.Finish()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Cannot finish signing data: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the signature
|
||||||
|
pem.Encode(os.Stdout, &pem.Block{Type: "PKCS7", Bytes: signed})
|
||||||
|
p7, err := pkcs7.Parse(signed)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Cannot parse our signed data: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// since the signature was detached, reattach the content here
|
||||||
|
p7.Content = content
|
||||||
|
|
||||||
|
if bytes.Compare(content, p7.Content) != 0 {
|
||||||
|
err = fmt.Errorf("Our content was not in the parsed data:\n\tExpected: %s\n\tActual: %s", content, p7.Content)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = p7.Verify(); err != nil {
|
||||||
|
err = fmt.Errorf("Cannot verify our signed data: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return signed, nil
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
This is a fork of [fullsailor/pkcs7](https://github.com/fullsailor/pkcs7)
|
95
vendor/github.com/fullsailor/pkcs7/ber.go → vendor/go.mozilla.org/pkcs7/ber.go
generated
vendored
95
vendor/github.com/fullsailor/pkcs7/ber.go → vendor/go.mozilla.org/pkcs7/ber.go
generated
vendored
@ -5,7 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// var encodeIndent = 0
|
var encodeIndent = 0
|
||||||
|
|
||||||
type asn1Object interface {
|
type asn1Object interface {
|
||||||
EncodeTo(writer *bytes.Buffer) error
|
EncodeTo(writer *bytes.Buffer) error
|
||||||
@ -18,7 +18,7 @@ type asn1Structured struct {
|
|||||||
|
|
||||||
func (s asn1Structured) EncodeTo(out *bytes.Buffer) error {
|
func (s asn1Structured) EncodeTo(out *bytes.Buffer) error {
|
||||||
//fmt.Printf("%s--> tag: % X\n", strings.Repeat("| ", encodeIndent), s.tagBytes)
|
//fmt.Printf("%s--> tag: % X\n", strings.Repeat("| ", encodeIndent), s.tagBytes)
|
||||||
//encodeIndent++
|
encodeIndent++
|
||||||
inner := new(bytes.Buffer)
|
inner := new(bytes.Buffer)
|
||||||
for _, obj := range s.content {
|
for _, obj := range s.content {
|
||||||
err := obj.EncodeTo(inner)
|
err := obj.EncodeTo(inner)
|
||||||
@ -26,7 +26,7 @@ func (s asn1Structured) EncodeTo(out *bytes.Buffer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//encodeIndent--
|
encodeIndent--
|
||||||
out.Write(s.tagBytes)
|
out.Write(s.tagBytes)
|
||||||
encodeLength(out, inner.Len())
|
encodeLength(out, inner.Len())
|
||||||
out.Write(inner.Bytes())
|
out.Write(inner.Bytes())
|
||||||
@ -133,35 +133,49 @@ func encodeLength(out *bytes.Buffer, length int) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func readObject(ber []byte, offset int) (asn1Object, int, error) {
|
func readObject(ber []byte, offset int) (asn1Object, int, error) {
|
||||||
//fmt.Printf("\n====> Starting readObject at offset: %d\n\n", offset)
|
berLen := len(ber)
|
||||||
|
if offset >= berLen {
|
||||||
|
return nil, 0, errors.New("ber2der: offset is after end of ber data")
|
||||||
|
}
|
||||||
tagStart := offset
|
tagStart := offset
|
||||||
b := ber[offset]
|
b := ber[offset]
|
||||||
offset++
|
offset++
|
||||||
|
if offset >= berLen {
|
||||||
|
return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
|
||||||
|
}
|
||||||
tag := b & 0x1F // last 5 bits
|
tag := b & 0x1F // last 5 bits
|
||||||
if tag == 0x1F {
|
if tag == 0x1F {
|
||||||
tag = 0
|
tag = 0
|
||||||
for ber[offset] >= 0x80 {
|
for ber[offset] >= 0x80 {
|
||||||
tag = tag*128 + ber[offset] - 0x80
|
tag = tag*128 + ber[offset] - 0x80
|
||||||
offset++
|
offset++
|
||||||
|
if offset > berLen {
|
||||||
|
return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
|
||||||
}
|
}
|
||||||
tag = tag*128 + ber[offset] - 0x80
|
}
|
||||||
|
// jvehent 20170227: this doesn't appear to be used anywhere...
|
||||||
|
//tag = tag*128 + ber[offset] - 0x80
|
||||||
offset++
|
offset++
|
||||||
|
if offset > berLen {
|
||||||
|
return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tagEnd := offset
|
tagEnd := offset
|
||||||
|
|
||||||
kind := b & 0x20
|
kind := b & 0x20
|
||||||
/*
|
|
||||||
if kind == 0 {
|
if kind == 0 {
|
||||||
fmt.Print("--> Primitive\n")
|
debugprint("--> Primitive\n")
|
||||||
} else {
|
} else {
|
||||||
fmt.Print("--> Constructed\n")
|
debugprint("--> Constructed\n")
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
// read length
|
// read length
|
||||||
var length int
|
var length int
|
||||||
l := ber[offset]
|
l := ber[offset]
|
||||||
offset++
|
offset++
|
||||||
indefinite := false
|
if offset > berLen {
|
||||||
|
return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
|
||||||
|
}
|
||||||
|
hack := 0
|
||||||
if l > 0x80 {
|
if l > 0x80 {
|
||||||
numberOfBytes := (int)(l & 0x7F)
|
numberOfBytes := (int)(l & 0x7F)
|
||||||
if numberOfBytes > 4 { // int is only guaranteed to be 32bit
|
if numberOfBytes > 4 { // int is only guaranteed to be 32bit
|
||||||
@ -170,33 +184,42 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
|
|||||||
if numberOfBytes == 4 && (int)(ber[offset]) > 0x7F {
|
if numberOfBytes == 4 && (int)(ber[offset]) > 0x7F {
|
||||||
return nil, 0, errors.New("ber2der: BER tag length is negative")
|
return nil, 0, errors.New("ber2der: BER tag length is negative")
|
||||||
}
|
}
|
||||||
if 0x0 == (int)(ber[offset]) {
|
if (int)(ber[offset]) == 0x0 {
|
||||||
return nil, 0, errors.New("ber2der: BER tag length has leading zero")
|
return nil, 0, errors.New("ber2der: BER tag length has leading zero")
|
||||||
}
|
}
|
||||||
//fmt.Printf("--> (compute length) indicator byte: %x\n", l)
|
debugprint("--> (compute length) indicator byte: %x\n", l)
|
||||||
//fmt.Printf("--> (compute length) length bytes: % X\n", ber[offset:offset+numberOfBytes])
|
debugprint("--> (compute length) length bytes: % X\n", ber[offset:offset+numberOfBytes])
|
||||||
for i := 0; i < numberOfBytes; i++ {
|
for i := 0; i < numberOfBytes; i++ {
|
||||||
length = length*256 + (int)(ber[offset])
|
length = length*256 + (int)(ber[offset])
|
||||||
offset++
|
offset++
|
||||||
|
if offset > berLen {
|
||||||
|
return nil, 0, errors.New("ber2der: cannot move offset forward, end of ber data reached")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if l == 0x80 {
|
} else if l == 0x80 {
|
||||||
indefinite = true
|
// find length by searching content
|
||||||
|
markerIndex := bytes.LastIndex(ber[offset:], []byte{0x0, 0x0})
|
||||||
|
if markerIndex == -1 {
|
||||||
|
return nil, 0, errors.New("ber2der: Invalid BER format")
|
||||||
|
}
|
||||||
|
length = markerIndex
|
||||||
|
hack = 2
|
||||||
|
debugprint("--> (compute length) marker found at offset: %d\n", markerIndex+offset)
|
||||||
} else {
|
} else {
|
||||||
length = (int)(l)
|
length = (int)(l)
|
||||||
}
|
}
|
||||||
|
if length < 0 {
|
||||||
|
return nil, 0, errors.New("ber2der: invalid negative value found in BER tag length")
|
||||||
|
}
|
||||||
//fmt.Printf("--> length : %d\n", length)
|
//fmt.Printf("--> length : %d\n", length)
|
||||||
contentEnd := offset + length
|
contentEnd := offset + length
|
||||||
if contentEnd > len(ber) {
|
if contentEnd > len(ber) {
|
||||||
return nil, 0, errors.New("ber2der: BER tag length is more than available data")
|
return nil, 0, errors.New("ber2der: BER tag length is more than available data")
|
||||||
}
|
}
|
||||||
//fmt.Printf("--> content start : %d\n", offset)
|
debugprint("--> content start : %d\n", offset)
|
||||||
//fmt.Printf("--> content end : %d\n", contentEnd)
|
debugprint("--> content end : %d\n", contentEnd)
|
||||||
//fmt.Printf("--> content : % X\n", ber[offset:contentEnd])
|
debugprint("--> content : % X\n", ber[offset:contentEnd])
|
||||||
var obj asn1Object
|
var obj asn1Object
|
||||||
if indefinite && kind == 0 {
|
|
||||||
return nil, 0, errors.New("ber2der: Indefinite form tag must have constructed encoding")
|
|
||||||
}
|
|
||||||
if kind == 0 {
|
if kind == 0 {
|
||||||
obj = asn1Primitive{
|
obj = asn1Primitive{
|
||||||
tagBytes: ber[tagStart:tagEnd],
|
tagBytes: ber[tagStart:tagEnd],
|
||||||
@ -205,25 +228,14 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var subObjects []asn1Object
|
var subObjects []asn1Object
|
||||||
for (offset < contentEnd) || indefinite {
|
for offset < contentEnd {
|
||||||
var subObj asn1Object
|
var subObj asn1Object
|
||||||
var err error
|
var err error
|
||||||
subObj, offset, err = readObject(ber, offset)
|
subObj, offset, err = readObject(ber[:contentEnd], offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
subObjects = append(subObjects, subObj)
|
subObjects = append(subObjects, subObj)
|
||||||
|
|
||||||
if indefinite {
|
|
||||||
terminated, err := isIndefiniteTermination(ber, offset)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if terminated {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
obj = asn1Structured{
|
obj = asn1Structured{
|
||||||
tagBytes: ber[tagStart:tagEnd],
|
tagBytes: ber[tagStart:tagEnd],
|
||||||
@ -231,18 +243,9 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply indefinite form length with 0x0000 terminator.
|
return obj, contentEnd + hack, nil
|
||||||
if indefinite {
|
|
||||||
contentEnd = offset + 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj, contentEnd, nil
|
func debugprint(format string, a ...interface{}) {
|
||||||
}
|
//fmt.Printf(format, a)
|
||||||
|
|
||||||
func isIndefiniteTermination(ber []byte, offset int) (bool, error) {
|
|
||||||
if len(ber) - offset < 2 {
|
|
||||||
return false, errors.New("ber2der: Invalid BER format")
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes.Index(ber[offset:], []byte{0x0, 0x0}) == 0, nil
|
|
||||||
}
|
}
|
177
vendor/go.mozilla.org/pkcs7/decrypt.go
generated
vendored
Normal file
177
vendor/go.mozilla.org/pkcs7/decrypt.go
generated
vendored
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package pkcs7
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/des"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/asn1"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrUnsupportedAlgorithm tells you when our quick dev assumptions have failed
|
||||||
|
var ErrUnsupportedAlgorithm = errors.New("pkcs7: cannot decrypt data: only RSA, DES, DES-EDE3, AES-256-CBC and AES-128-GCM supported")
|
||||||
|
|
||||||
|
// ErrNotEncryptedContent is returned when attempting to Decrypt data that is not encrypted data
|
||||||
|
var ErrNotEncryptedContent = errors.New("pkcs7: content data is a decryptable data type")
|
||||||
|
|
||||||
|
// Decrypt decrypts encrypted content info for recipient cert and private key
|
||||||
|
func (p7 *PKCS7) Decrypt(cert *x509.Certificate, pkey crypto.PrivateKey) ([]byte, error) {
|
||||||
|
data, ok := p7.raw.(envelopedData)
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrNotEncryptedContent
|
||||||
|
}
|
||||||
|
recipient := selectRecipientForCertificate(data.RecipientInfos, cert)
|
||||||
|
if recipient.EncryptedKey == nil {
|
||||||
|
return nil, errors.New("pkcs7: no enveloped recipient for provided certificate")
|
||||||
|
}
|
||||||
|
switch pkey := pkey.(type) {
|
||||||
|
case *rsa.PrivateKey:
|
||||||
|
var contentKey []byte
|
||||||
|
contentKey, err := rsa.DecryptPKCS1v15(rand.Reader, pkey, recipient.EncryptedKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return data.EncryptedContentInfo.decrypt(contentKey)
|
||||||
|
}
|
||||||
|
return nil, ErrUnsupportedAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecryptUsingPSK decrypts encrypted data using caller provided
|
||||||
|
// pre-shared secret
|
||||||
|
func (p7 *PKCS7) DecryptUsingPSK(key []byte) ([]byte, error) {
|
||||||
|
data, ok := p7.raw.(encryptedData)
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrNotEncryptedContent
|
||||||
|
}
|
||||||
|
return data.EncryptedContentInfo.decrypt(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eci encryptedContentInfo) decrypt(key []byte) ([]byte, error) {
|
||||||
|
alg := eci.ContentEncryptionAlgorithm.Algorithm
|
||||||
|
if !alg.Equal(OIDEncryptionAlgorithmDESCBC) &&
|
||||||
|
!alg.Equal(OIDEncryptionAlgorithmDESEDE3CBC) &&
|
||||||
|
!alg.Equal(OIDEncryptionAlgorithmAES256CBC) &&
|
||||||
|
!alg.Equal(OIDEncryptionAlgorithmAES128CBC) &&
|
||||||
|
!alg.Equal(OIDEncryptionAlgorithmAES128GCM) &&
|
||||||
|
!alg.Equal(OIDEncryptionAlgorithmAES256GCM) {
|
||||||
|
fmt.Printf("Unsupported Content Encryption Algorithm: %s\n", alg)
|
||||||
|
return nil, ErrUnsupportedAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncryptedContent can either be constructed of multple OCTET STRINGs
|
||||||
|
// or _be_ a tagged OCTET STRING
|
||||||
|
var cyphertext []byte
|
||||||
|
if eci.EncryptedContent.IsCompound {
|
||||||
|
// Complex case to concat all of the children OCTET STRINGs
|
||||||
|
var buf bytes.Buffer
|
||||||
|
cypherbytes := eci.EncryptedContent.Bytes
|
||||||
|
for {
|
||||||
|
var part []byte
|
||||||
|
cypherbytes, _ = asn1.Unmarshal(cypherbytes, &part)
|
||||||
|
buf.Write(part)
|
||||||
|
if cypherbytes == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cyphertext = buf.Bytes()
|
||||||
|
} else {
|
||||||
|
// Simple case, the bytes _are_ the cyphertext
|
||||||
|
cyphertext = eci.EncryptedContent.Bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
var block cipher.Block
|
||||||
|
var err error
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case alg.Equal(OIDEncryptionAlgorithmDESCBC):
|
||||||
|
block, err = des.NewCipher(key)
|
||||||
|
case alg.Equal(OIDEncryptionAlgorithmDESEDE3CBC):
|
||||||
|
block, err = des.NewTripleDESCipher(key)
|
||||||
|
case alg.Equal(OIDEncryptionAlgorithmAES256CBC), alg.Equal(OIDEncryptionAlgorithmAES256GCM):
|
||||||
|
fallthrough
|
||||||
|
case alg.Equal(OIDEncryptionAlgorithmAES128GCM), alg.Equal(OIDEncryptionAlgorithmAES128CBC):
|
||||||
|
block, err = aes.NewCipher(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if alg.Equal(OIDEncryptionAlgorithmAES128GCM) || alg.Equal(OIDEncryptionAlgorithmAES256GCM) {
|
||||||
|
params := aesGCMParameters{}
|
||||||
|
paramBytes := eci.ContentEncryptionAlgorithm.Parameters.Bytes
|
||||||
|
|
||||||
|
_, err := asn1.Unmarshal(paramBytes, ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gcm, err := cipher.NewGCM(block)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(params.Nonce) != gcm.NonceSize() {
|
||||||
|
return nil, errors.New("pkcs7: encryption algorithm parameters are incorrect")
|
||||||
|
}
|
||||||
|
if params.ICVLen != gcm.Overhead() {
|
||||||
|
return nil, errors.New("pkcs7: encryption algorithm parameters are incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
plaintext, err := gcm.Open(nil, params.Nonce, cyphertext, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return plaintext, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := eci.ContentEncryptionAlgorithm.Parameters.Bytes
|
||||||
|
if len(iv) != block.BlockSize() {
|
||||||
|
return nil, errors.New("pkcs7: encryption algorithm parameters are malformed")
|
||||||
|
}
|
||||||
|
mode := cipher.NewCBCDecrypter(block, iv)
|
||||||
|
plaintext := make([]byte, len(cyphertext))
|
||||||
|
mode.CryptBlocks(plaintext, cyphertext)
|
||||||
|
if plaintext, err = unpad(plaintext, mode.BlockSize()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return plaintext, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unpad(data []byte, blocklen int) ([]byte, error) {
|
||||||
|
if blocklen < 1 {
|
||||||
|
return nil, fmt.Errorf("invalid blocklen %d", blocklen)
|
||||||
|
}
|
||||||
|
if len(data)%blocklen != 0 || len(data) == 0 {
|
||||||
|
return nil, fmt.Errorf("invalid data len %d", len(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// the last byte is the length of padding
|
||||||
|
padlen := int(data[len(data)-1])
|
||||||
|
|
||||||
|
// check padding integrity, all bytes should be the same
|
||||||
|
pad := data[len(data)-padlen:]
|
||||||
|
for _, padbyte := range pad {
|
||||||
|
if padbyte != byte(padlen) {
|
||||||
|
return nil, errors.New("invalid padding")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data[:len(data)-padlen], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func selectRecipientForCertificate(recipients []recipientInfo, cert *x509.Certificate) recipientInfo {
|
||||||
|
for _, recp := range recipients {
|
||||||
|
if isCertMatchForIssuerAndSerial(cert, recp.IssuerAndSerialNumber) {
|
||||||
|
return recp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return recipientInfo{}
|
||||||
|
}
|
399
vendor/go.mozilla.org/pkcs7/encrypt.go
generated
vendored
Normal file
399
vendor/go.mozilla.org/pkcs7/encrypt.go
generated
vendored
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
package pkcs7
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/des"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/asn1"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type envelopedData struct {
|
||||||
|
Version int
|
||||||
|
RecipientInfos []recipientInfo `asn1:"set"`
|
||||||
|
EncryptedContentInfo encryptedContentInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type encryptedData struct {
|
||||||
|
Version int
|
||||||
|
EncryptedContentInfo encryptedContentInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type recipientInfo struct {
|
||||||
|
Version int
|
||||||
|
IssuerAndSerialNumber issuerAndSerial
|
||||||
|
KeyEncryptionAlgorithm pkix.AlgorithmIdentifier
|
||||||
|
EncryptedKey []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type encryptedContentInfo struct {
|
||||||
|
ContentType asn1.ObjectIdentifier
|
||||||
|
ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
|
||||||
|
EncryptedContent asn1.RawValue `asn1:"tag:0,optional,explicit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// EncryptionAlgorithmDESCBC is the DES CBC encryption algorithm
|
||||||
|
EncryptionAlgorithmDESCBC = iota
|
||||||
|
|
||||||
|
// EncryptionAlgorithmAES128CBC is the AES 128 bits with CBC encryption algorithm
|
||||||
|
// Avoid this algorithm unless required for interoperability; use AES GCM instead.
|
||||||
|
EncryptionAlgorithmAES128CBC
|
||||||
|
|
||||||
|
// EncryptionAlgorithmAES256CBC is the AES 256 bits with CBC encryption algorithm
|
||||||
|
// Avoid this algorithm unless required for interoperability; use AES GCM instead.
|
||||||
|
EncryptionAlgorithmAES256CBC
|
||||||
|
|
||||||
|
// EncryptionAlgorithmAES128GCM is the AES 128 bits with GCM encryption algorithm
|
||||||
|
EncryptionAlgorithmAES128GCM
|
||||||
|
|
||||||
|
// EncryptionAlgorithmAES256GCM is the AES 256 bits with GCM encryption algorithm
|
||||||
|
EncryptionAlgorithmAES256GCM
|
||||||
|
)
|
||||||
|
|
||||||
|
// ContentEncryptionAlgorithm determines the algorithm used to encrypt the
|
||||||
|
// plaintext message. Change the value of this variable to change which
|
||||||
|
// algorithm is used in the Encrypt() function.
|
||||||
|
var ContentEncryptionAlgorithm = EncryptionAlgorithmDESCBC
|
||||||
|
|
||||||
|
// ErrUnsupportedEncryptionAlgorithm is returned when attempting to encrypt
|
||||||
|
// content with an unsupported algorithm.
|
||||||
|
var ErrUnsupportedEncryptionAlgorithm = errors.New("pkcs7: cannot encrypt content: only DES-CBC, AES-CBC, and AES-GCM supported")
|
||||||
|
|
||||||
|
// ErrPSKNotProvided is returned when attempting to encrypt
|
||||||
|
// using a PSK without actually providing the PSK.
|
||||||
|
var ErrPSKNotProvided = errors.New("pkcs7: cannot encrypt content: PSK not provided")
|
||||||
|
|
||||||
|
const nonceSize = 12
|
||||||
|
|
||||||
|
type aesGCMParameters struct {
|
||||||
|
Nonce []byte `asn1:"tag:4"`
|
||||||
|
ICVLen int
|
||||||
|
}
|
||||||
|
|
||||||
|
func encryptAESGCM(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
|
||||||
|
var keyLen int
|
||||||
|
var algID asn1.ObjectIdentifier
|
||||||
|
switch ContentEncryptionAlgorithm {
|
||||||
|
case EncryptionAlgorithmAES128GCM:
|
||||||
|
keyLen = 16
|
||||||
|
algID = OIDEncryptionAlgorithmAES128GCM
|
||||||
|
case EncryptionAlgorithmAES256GCM:
|
||||||
|
keyLen = 32
|
||||||
|
algID = OIDEncryptionAlgorithmAES256GCM
|
||||||
|
default:
|
||||||
|
return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptAESGCM: %d", ContentEncryptionAlgorithm)
|
||||||
|
}
|
||||||
|
if key == nil {
|
||||||
|
// Create AES key
|
||||||
|
key = make([]byte, keyLen)
|
||||||
|
|
||||||
|
_, err := rand.Read(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create nonce
|
||||||
|
nonce := make([]byte, nonceSize)
|
||||||
|
|
||||||
|
_, err := rand.Read(nonce)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt content
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gcm, err := cipher.NewGCM(block)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ciphertext := gcm.Seal(nil, nonce, content, nil)
|
||||||
|
|
||||||
|
// Prepare ASN.1 Encrypted Content Info
|
||||||
|
paramSeq := aesGCMParameters{
|
||||||
|
Nonce: nonce,
|
||||||
|
ICVLen: gcm.Overhead(),
|
||||||
|
}
|
||||||
|
|
||||||
|
paramBytes, err := asn1.Marshal(paramSeq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
eci := encryptedContentInfo{
|
||||||
|
ContentType: OIDData,
|
||||||
|
ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
|
||||||
|
Algorithm: algID,
|
||||||
|
Parameters: asn1.RawValue{
|
||||||
|
Tag: asn1.TagSequence,
|
||||||
|
Bytes: paramBytes,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
EncryptedContent: marshalEncryptedContent(ciphertext),
|
||||||
|
}
|
||||||
|
|
||||||
|
return key, &eci, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encryptDESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
|
||||||
|
if key == nil {
|
||||||
|
// Create DES key
|
||||||
|
key = make([]byte, 8)
|
||||||
|
|
||||||
|
_, err := rand.Read(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create CBC IV
|
||||||
|
iv := make([]byte, des.BlockSize)
|
||||||
|
_, err := rand.Read(iv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt padded content
|
||||||
|
block, err := des.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
mode := cipher.NewCBCEncrypter(block, iv)
|
||||||
|
plaintext, err := pad(content, mode.BlockSize())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
cyphertext := make([]byte, len(plaintext))
|
||||||
|
mode.CryptBlocks(cyphertext, plaintext)
|
||||||
|
|
||||||
|
// Prepare ASN.1 Encrypted Content Info
|
||||||
|
eci := encryptedContentInfo{
|
||||||
|
ContentType: OIDData,
|
||||||
|
ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
|
||||||
|
Algorithm: OIDEncryptionAlgorithmDESCBC,
|
||||||
|
Parameters: asn1.RawValue{Tag: 4, Bytes: iv},
|
||||||
|
},
|
||||||
|
EncryptedContent: marshalEncryptedContent(cyphertext),
|
||||||
|
}
|
||||||
|
|
||||||
|
return key, &eci, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func encryptAESCBC(content []byte, key []byte) ([]byte, *encryptedContentInfo, error) {
|
||||||
|
var keyLen int
|
||||||
|
var algID asn1.ObjectIdentifier
|
||||||
|
switch ContentEncryptionAlgorithm {
|
||||||
|
case EncryptionAlgorithmAES128CBC:
|
||||||
|
keyLen = 16
|
||||||
|
algID = OIDEncryptionAlgorithmAES128CBC
|
||||||
|
case EncryptionAlgorithmAES256CBC:
|
||||||
|
keyLen = 32
|
||||||
|
algID = OIDEncryptionAlgorithmAES256CBC
|
||||||
|
default:
|
||||||
|
return nil, nil, fmt.Errorf("invalid ContentEncryptionAlgorithm in encryptAESCBC: %d", ContentEncryptionAlgorithm)
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == nil {
|
||||||
|
// Create AES key
|
||||||
|
key = make([]byte, keyLen)
|
||||||
|
|
||||||
|
_, err := rand.Read(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create CBC IV
|
||||||
|
iv := make([]byte, aes.BlockSize)
|
||||||
|
_, err := rand.Read(iv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt padded content
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
mode := cipher.NewCBCEncrypter(block, iv)
|
||||||
|
plaintext, err := pad(content, mode.BlockSize())
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
cyphertext := make([]byte, len(plaintext))
|
||||||
|
mode.CryptBlocks(cyphertext, plaintext)
|
||||||
|
|
||||||
|
// Prepare ASN.1 Encrypted Content Info
|
||||||
|
eci := encryptedContentInfo{
|
||||||
|
ContentType: OIDData,
|
||||||
|
ContentEncryptionAlgorithm: pkix.AlgorithmIdentifier{
|
||||||
|
Algorithm: algID,
|
||||||
|
Parameters: asn1.RawValue{Tag: 4, Bytes: iv},
|
||||||
|
},
|
||||||
|
EncryptedContent: marshalEncryptedContent(cyphertext),
|
||||||
|
}
|
||||||
|
|
||||||
|
return key, &eci, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt creates and returns an envelope data PKCS7 structure with encrypted
|
||||||
|
// recipient keys for each recipient public key.
|
||||||
|
//
|
||||||
|
// The algorithm used to perform encryption is determined by the current value
|
||||||
|
// of the global ContentEncryptionAlgorithm package variable. By default, the
|
||||||
|
// value is EncryptionAlgorithmDESCBC. To use a different algorithm, change the
|
||||||
|
// value before calling Encrypt(). For example:
|
||||||
|
//
|
||||||
|
// ContentEncryptionAlgorithm = EncryptionAlgorithmAES128GCM
|
||||||
|
//
|
||||||
|
// TODO(fullsailor): Add support for encrypting content with other algorithms
|
||||||
|
func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error) {
|
||||||
|
var eci *encryptedContentInfo
|
||||||
|
var key []byte
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Apply chosen symmetric encryption method
|
||||||
|
switch ContentEncryptionAlgorithm {
|
||||||
|
case EncryptionAlgorithmDESCBC:
|
||||||
|
key, eci, err = encryptDESCBC(content, nil)
|
||||||
|
case EncryptionAlgorithmAES128CBC:
|
||||||
|
fallthrough
|
||||||
|
case EncryptionAlgorithmAES256CBC:
|
||||||
|
key, eci, err = encryptAESCBC(content, nil)
|
||||||
|
case EncryptionAlgorithmAES128GCM:
|
||||||
|
fallthrough
|
||||||
|
case EncryptionAlgorithmAES256GCM:
|
||||||
|
key, eci, err = encryptAESGCM(content, nil)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, ErrUnsupportedEncryptionAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare each recipient's encrypted cipher key
|
||||||
|
recipientInfos := make([]recipientInfo, len(recipients))
|
||||||
|
for i, recipient := range recipients {
|
||||||
|
encrypted, err := encryptKey(key, recipient)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ias, err := cert2issuerAndSerial(recipient)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
info := recipientInfo{
|
||||||
|
Version: 0,
|
||||||
|
IssuerAndSerialNumber: ias,
|
||||||
|
KeyEncryptionAlgorithm: pkix.AlgorithmIdentifier{
|
||||||
|
Algorithm: OIDEncryptionAlgorithmRSA,
|
||||||
|
},
|
||||||
|
EncryptedKey: encrypted,
|
||||||
|
}
|
||||||
|
recipientInfos[i] = info
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare envelope content
|
||||||
|
envelope := envelopedData{
|
||||||
|
EncryptedContentInfo: *eci,
|
||||||
|
Version: 0,
|
||||||
|
RecipientInfos: recipientInfos,
|
||||||
|
}
|
||||||
|
innerContent, err := asn1.Marshal(envelope)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare outer payload structure
|
||||||
|
wrapper := contentInfo{
|
||||||
|
ContentType: OIDEnvelopedData,
|
||||||
|
Content: asn1.RawValue{Class: 2, Tag: 0, IsCompound: true, Bytes: innerContent},
|
||||||
|
}
|
||||||
|
|
||||||
|
return asn1.Marshal(wrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncryptUsingPSK creates and returns an encrypted data PKCS7 structure,
|
||||||
|
// encrypted using caller provided pre-shared secret.
|
||||||
|
func EncryptUsingPSK(content []byte, key []byte) ([]byte, error) {
|
||||||
|
var eci *encryptedContentInfo
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if key == nil {
|
||||||
|
return nil, ErrPSKNotProvided
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply chosen symmetric encryption method
|
||||||
|
switch ContentEncryptionAlgorithm {
|
||||||
|
case EncryptionAlgorithmDESCBC:
|
||||||
|
_, eci, err = encryptDESCBC(content, key)
|
||||||
|
|
||||||
|
case EncryptionAlgorithmAES128GCM:
|
||||||
|
fallthrough
|
||||||
|
case EncryptionAlgorithmAES256GCM:
|
||||||
|
_, eci, err = encryptAESGCM(content, key)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, ErrUnsupportedEncryptionAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare encrypted-data content
|
||||||
|
ed := encryptedData{
|
||||||
|
Version: 0,
|
||||||
|
EncryptedContentInfo: *eci,
|
||||||
|
}
|
||||||
|
innerContent, err := asn1.Marshal(ed)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare outer payload structure
|
||||||
|
wrapper := contentInfo{
|
||||||
|
ContentType: OIDEncryptedData,
|
||||||
|
Content: asn1.RawValue{Class: 2, Tag: 0, IsCompound: true, Bytes: innerContent},
|
||||||
|
}
|
||||||
|
|
||||||
|
return asn1.Marshal(wrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalEncryptedContent(content []byte) asn1.RawValue {
|
||||||
|
asn1Content, _ := asn1.Marshal(content)
|
||||||
|
return asn1.RawValue{Tag: 0, Class: 2, Bytes: asn1Content, IsCompound: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func encryptKey(key []byte, recipient *x509.Certificate) ([]byte, error) {
|
||||||
|
if pub := recipient.PublicKey.(*rsa.PublicKey); pub != nil {
|
||||||
|
return rsa.EncryptPKCS1v15(rand.Reader, pub, key)
|
||||||
|
}
|
||||||
|
return nil, ErrUnsupportedAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
func pad(data []byte, blocklen int) ([]byte, error) {
|
||||||
|
if blocklen < 1 {
|
||||||
|
return nil, fmt.Errorf("invalid blocklen %d", blocklen)
|
||||||
|
}
|
||||||
|
padlen := blocklen - (len(data) % blocklen)
|
||||||
|
if padlen == 0 {
|
||||||
|
padlen = blocklen
|
||||||
|
}
|
||||||
|
pad := bytes.Repeat([]byte{byte(padlen)}, padlen)
|
||||||
|
return append(data, pad...), nil
|
||||||
|
}
|
3
vendor/go.mozilla.org/pkcs7/go.mod
generated
vendored
Normal file
3
vendor/go.mozilla.org/pkcs7/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module go.mozilla.org/pkcs7
|
||||||
|
|
||||||
|
go 1.11
|
291
vendor/go.mozilla.org/pkcs7/pkcs7.go
generated
vendored
Normal file
291
vendor/go.mozilla.org/pkcs7/pkcs7.go
generated
vendored
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
// Package pkcs7 implements parsing and generation of some PKCS#7 structures.
|
||||||
|
package pkcs7
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
"crypto/dsa"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/asn1"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
_ "crypto/sha1" // for crypto.SHA1
|
||||||
|
)
|
||||||
|
|
||||||
|
// PKCS7 Represents a PKCS7 structure
|
||||||
|
type PKCS7 struct {
|
||||||
|
Content []byte
|
||||||
|
Certificates []*x509.Certificate
|
||||||
|
CRLs []pkix.CertificateList
|
||||||
|
Signers []signerInfo
|
||||||
|
raw interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type contentInfo struct {
|
||||||
|
ContentType asn1.ObjectIdentifier
|
||||||
|
Content asn1.RawValue `asn1:"explicit,optional,tag:0"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrUnsupportedContentType is returned when a PKCS7 content is not supported.
|
||||||
|
// Currently only Data (1.2.840.113549.1.7.1), Signed Data (1.2.840.113549.1.7.2),
|
||||||
|
// and Enveloped Data are supported (1.2.840.113549.1.7.3)
|
||||||
|
var ErrUnsupportedContentType = errors.New("pkcs7: cannot parse data: unimplemented content type")
|
||||||
|
|
||||||
|
type unsignedData []byte
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Signed Data OIDs
|
||||||
|
OIDData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1}
|
||||||
|
OIDSignedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2}
|
||||||
|
OIDEnvelopedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 3}
|
||||||
|
OIDEncryptedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 6}
|
||||||
|
OIDAttributeContentType = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 3}
|
||||||
|
OIDAttributeMessageDigest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 4}
|
||||||
|
OIDAttributeSigningTime = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 5}
|
||||||
|
|
||||||
|
// Digest Algorithms
|
||||||
|
OIDDigestAlgorithmSHA1 = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26}
|
||||||
|
OIDDigestAlgorithmSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1}
|
||||||
|
OIDDigestAlgorithmSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2}
|
||||||
|
OIDDigestAlgorithmSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3}
|
||||||
|
|
||||||
|
OIDDigestAlgorithmDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
|
||||||
|
OIDDigestAlgorithmDSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
|
||||||
|
|
||||||
|
OIDDigestAlgorithmECDSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
|
||||||
|
OIDDigestAlgorithmECDSASHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
|
||||||
|
OIDDigestAlgorithmECDSASHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
|
||||||
|
OIDDigestAlgorithmECDSASHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
|
||||||
|
|
||||||
|
// Signature Algorithms
|
||||||
|
OIDEncryptionAlgorithmRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
|
||||||
|
OIDEncryptionAlgorithmRSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
|
||||||
|
OIDEncryptionAlgorithmRSASHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
|
||||||
|
OIDEncryptionAlgorithmRSASHA384 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
|
||||||
|
OIDEncryptionAlgorithmRSASHA512 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
|
||||||
|
|
||||||
|
OIDEncryptionAlgorithmECDSAP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
|
||||||
|
OIDEncryptionAlgorithmECDSAP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
|
||||||
|
OIDEncryptionAlgorithmECDSAP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
|
||||||
|
|
||||||
|
// Encryption Algorithms
|
||||||
|
OIDEncryptionAlgorithmDESCBC = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7}
|
||||||
|
OIDEncryptionAlgorithmDESEDE3CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7}
|
||||||
|
OIDEncryptionAlgorithmAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42}
|
||||||
|
OIDEncryptionAlgorithmAES128GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 6}
|
||||||
|
OIDEncryptionAlgorithmAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}
|
||||||
|
OIDEncryptionAlgorithmAES256GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 46}
|
||||||
|
)
|
||||||
|
|
||||||
|
func getHashForOID(oid asn1.ObjectIdentifier) (crypto.Hash, error) {
|
||||||
|
switch {
|
||||||
|
case oid.Equal(OIDDigestAlgorithmSHA1), oid.Equal(OIDDigestAlgorithmECDSASHA1),
|
||||||
|
oid.Equal(OIDDigestAlgorithmDSA), oid.Equal(OIDDigestAlgorithmDSASHA1),
|
||||||
|
oid.Equal(OIDEncryptionAlgorithmRSA):
|
||||||
|
return crypto.SHA1, nil
|
||||||
|
case oid.Equal(OIDDigestAlgorithmSHA256), oid.Equal(OIDDigestAlgorithmECDSASHA256):
|
||||||
|
return crypto.SHA256, nil
|
||||||
|
case oid.Equal(OIDDigestAlgorithmSHA384), oid.Equal(OIDDigestAlgorithmECDSASHA384):
|
||||||
|
return crypto.SHA384, nil
|
||||||
|
case oid.Equal(OIDDigestAlgorithmSHA512), oid.Equal(OIDDigestAlgorithmECDSASHA512):
|
||||||
|
return crypto.SHA512, nil
|
||||||
|
}
|
||||||
|
return crypto.Hash(0), ErrUnsupportedAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDigestOIDForSignatureAlgorithm takes an x509.SignatureAlgorithm
|
||||||
|
// and returns the corresponding OID digest algorithm
|
||||||
|
func getDigestOIDForSignatureAlgorithm(digestAlg x509.SignatureAlgorithm) (asn1.ObjectIdentifier, error) {
|
||||||
|
switch digestAlg {
|
||||||
|
case x509.SHA1WithRSA, x509.ECDSAWithSHA1:
|
||||||
|
return OIDDigestAlgorithmSHA1, nil
|
||||||
|
case x509.SHA256WithRSA, x509.ECDSAWithSHA256:
|
||||||
|
return OIDDigestAlgorithmSHA256, nil
|
||||||
|
case x509.SHA384WithRSA, x509.ECDSAWithSHA384:
|
||||||
|
return OIDDigestAlgorithmSHA384, nil
|
||||||
|
case x509.SHA512WithRSA, x509.ECDSAWithSHA512:
|
||||||
|
return OIDDigestAlgorithmSHA512, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("pkcs7: cannot convert hash to oid, unknown hash algorithm")
|
||||||
|
}
|
||||||
|
|
||||||
|
// getOIDForEncryptionAlgorithm takes the private key type of the signer and
|
||||||
|
// the OID of a digest algorithm to return the appropriate signerInfo.DigestEncryptionAlgorithm
|
||||||
|
func getOIDForEncryptionAlgorithm(pkey crypto.PrivateKey, OIDDigestAlg asn1.ObjectIdentifier) (asn1.ObjectIdentifier, error) {
|
||||||
|
switch pkey.(type) {
|
||||||
|
case *rsa.PrivateKey:
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
return OIDEncryptionAlgorithmRSA, nil
|
||||||
|
case OIDDigestAlg.Equal(OIDEncryptionAlgorithmRSA):
|
||||||
|
return OIDEncryptionAlgorithmRSA, nil
|
||||||
|
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA1):
|
||||||
|
return OIDEncryptionAlgorithmRSASHA1, nil
|
||||||
|
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA256):
|
||||||
|
return OIDEncryptionAlgorithmRSASHA256, nil
|
||||||
|
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA384):
|
||||||
|
return OIDEncryptionAlgorithmRSASHA384, nil
|
||||||
|
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA512):
|
||||||
|
return OIDEncryptionAlgorithmRSASHA512, nil
|
||||||
|
}
|
||||||
|
case *ecdsa.PrivateKey:
|
||||||
|
switch {
|
||||||
|
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA1):
|
||||||
|
return OIDDigestAlgorithmECDSASHA1, nil
|
||||||
|
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA256):
|
||||||
|
return OIDDigestAlgorithmECDSASHA256, nil
|
||||||
|
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA384):
|
||||||
|
return OIDDigestAlgorithmECDSASHA384, nil
|
||||||
|
case OIDDigestAlg.Equal(OIDDigestAlgorithmSHA512):
|
||||||
|
return OIDDigestAlgorithmECDSASHA512, nil
|
||||||
|
}
|
||||||
|
case *dsa.PrivateKey:
|
||||||
|
return OIDDigestAlgorithmDSA, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("pkcs7: cannot convert encryption algorithm to oid, unknown private key type %T", pkey)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse decodes a DER encoded PKCS7 package
|
||||||
|
func Parse(data []byte) (p7 *PKCS7, err error) {
|
||||||
|
if len(data) == 0 {
|
||||||
|
return nil, errors.New("pkcs7: input data is empty")
|
||||||
|
}
|
||||||
|
var info contentInfo
|
||||||
|
der, err := ber2der(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rest, err := asn1.Unmarshal(der, &info)
|
||||||
|
if len(rest) > 0 {
|
||||||
|
err = asn1.SyntaxError{Msg: "trailing data"}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt.Printf("--> Content Type: %s", info.ContentType)
|
||||||
|
switch {
|
||||||
|
case info.ContentType.Equal(OIDSignedData):
|
||||||
|
return parseSignedData(info.Content.Bytes)
|
||||||
|
case info.ContentType.Equal(OIDEnvelopedData):
|
||||||
|
return parseEnvelopedData(info.Content.Bytes)
|
||||||
|
case info.ContentType.Equal(OIDEncryptedData):
|
||||||
|
return parseEncryptedData(info.Content.Bytes)
|
||||||
|
}
|
||||||
|
return nil, ErrUnsupportedContentType
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseEnvelopedData(data []byte) (*PKCS7, error) {
|
||||||
|
var ed envelopedData
|
||||||
|
if _, err := asn1.Unmarshal(data, &ed); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &PKCS7{
|
||||||
|
raw: ed,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseEncryptedData(data []byte) (*PKCS7, error) {
|
||||||
|
var ed encryptedData
|
||||||
|
if _, err := asn1.Unmarshal(data, &ed); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &PKCS7{
|
||||||
|
raw: ed,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (raw rawCertificates) Parse() ([]*x509.Certificate, error) {
|
||||||
|
if len(raw.Raw) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var val asn1.RawValue
|
||||||
|
if _, err := asn1.Unmarshal(raw.Raw, &val); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return x509.ParseCertificates(val.Bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isCertMatchForIssuerAndSerial(cert *x509.Certificate, ias issuerAndSerial) bool {
|
||||||
|
return cert.SerialNumber.Cmp(ias.SerialNumber) == 0 && bytes.Equal(cert.RawIssuer, ias.IssuerName.FullBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attribute represents a key value pair attribute. Value must be marshalable byte
|
||||||
|
// `encoding/asn1`
|
||||||
|
type Attribute struct {
|
||||||
|
Type asn1.ObjectIdentifier
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type attributes struct {
|
||||||
|
types []asn1.ObjectIdentifier
|
||||||
|
values []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the attribute, maintaining insertion order
|
||||||
|
func (attrs *attributes) Add(attrType asn1.ObjectIdentifier, value interface{}) {
|
||||||
|
attrs.types = append(attrs.types, attrType)
|
||||||
|
attrs.values = append(attrs.values, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
type sortableAttribute struct {
|
||||||
|
SortKey []byte
|
||||||
|
Attribute attribute
|
||||||
|
}
|
||||||
|
|
||||||
|
type attributeSet []sortableAttribute
|
||||||
|
|
||||||
|
func (sa attributeSet) Len() int {
|
||||||
|
return len(sa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sa attributeSet) Less(i, j int) bool {
|
||||||
|
return bytes.Compare(sa[i].SortKey, sa[j].SortKey) < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sa attributeSet) Swap(i, j int) {
|
||||||
|
sa[i], sa[j] = sa[j], sa[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sa attributeSet) Attributes() []attribute {
|
||||||
|
attrs := make([]attribute, len(sa))
|
||||||
|
for i, attr := range sa {
|
||||||
|
attrs[i] = attr.Attribute
|
||||||
|
}
|
||||||
|
return attrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (attrs *attributes) ForMarshalling() ([]attribute, error) {
|
||||||
|
sortables := make(attributeSet, len(attrs.types))
|
||||||
|
for i := range sortables {
|
||||||
|
attrType := attrs.types[i]
|
||||||
|
attrValue := attrs.values[i]
|
||||||
|
asn1Value, err := asn1.Marshal(attrValue)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
attr := attribute{
|
||||||
|
Type: attrType,
|
||||||
|
Value: asn1.RawValue{Tag: 17, IsCompound: true, Bytes: asn1Value}, // 17 == SET tag
|
||||||
|
}
|
||||||
|
encoded, err := asn1.Marshal(attr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sortables[i] = sortableAttribute{
|
||||||
|
SortKey: encoded,
|
||||||
|
Attribute: attr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Sort(sortables)
|
||||||
|
return sortables.Attributes(), nil
|
||||||
|
}
|
429
vendor/go.mozilla.org/pkcs7/sign.go
generated
vendored
Normal file
429
vendor/go.mozilla.org/pkcs7/sign.go
generated
vendored
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
package pkcs7
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
"crypto/dsa"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/asn1"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SignedData is an opaque data structure for creating signed data payloads
|
||||||
|
type SignedData struct {
|
||||||
|
sd signedData
|
||||||
|
certs []*x509.Certificate
|
||||||
|
data, messageDigest []byte
|
||||||
|
digestOid asn1.ObjectIdentifier
|
||||||
|
encryptionOid asn1.ObjectIdentifier
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSignedData takes data and initializes a PKCS7 SignedData struct that is
|
||||||
|
// ready to be signed via AddSigner. The digest algorithm is set to SHA1 by default
|
||||||
|
// and can be changed by calling SetDigestAlgorithm.
|
||||||
|
func NewSignedData(data []byte) (*SignedData, error) {
|
||||||
|
content, err := asn1.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ci := contentInfo{
|
||||||
|
ContentType: OIDData,
|
||||||
|
Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true},
|
||||||
|
}
|
||||||
|
sd := signedData{
|
||||||
|
ContentInfo: ci,
|
||||||
|
Version: 1,
|
||||||
|
}
|
||||||
|
return &SignedData{sd: sd, data: data, digestOid: OIDDigestAlgorithmSHA1}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignerInfoConfig are optional values to include when adding a signer
|
||||||
|
type SignerInfoConfig struct {
|
||||||
|
ExtraSignedAttributes []Attribute
|
||||||
|
ExtraUnsignedAttributes []Attribute
|
||||||
|
}
|
||||||
|
|
||||||
|
type signedData struct {
|
||||||
|
Version int `asn1:"default:1"`
|
||||||
|
DigestAlgorithmIdentifiers []pkix.AlgorithmIdentifier `asn1:"set"`
|
||||||
|
ContentInfo contentInfo
|
||||||
|
Certificates rawCertificates `asn1:"optional,tag:0"`
|
||||||
|
CRLs []pkix.CertificateList `asn1:"optional,tag:1"`
|
||||||
|
SignerInfos []signerInfo `asn1:"set"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type signerInfo struct {
|
||||||
|
Version int `asn1:"default:1"`
|
||||||
|
IssuerAndSerialNumber issuerAndSerial
|
||||||
|
DigestAlgorithm pkix.AlgorithmIdentifier
|
||||||
|
AuthenticatedAttributes []attribute `asn1:"optional,omitempty,tag:0"`
|
||||||
|
DigestEncryptionAlgorithm pkix.AlgorithmIdentifier
|
||||||
|
EncryptedDigest []byte
|
||||||
|
UnauthenticatedAttributes []attribute `asn1:"optional,omitempty,tag:1"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type attribute struct {
|
||||||
|
Type asn1.ObjectIdentifier
|
||||||
|
Value asn1.RawValue `asn1:"set"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalAttributes(attrs []attribute) ([]byte, error) {
|
||||||
|
encodedAttributes, err := asn1.Marshal(struct {
|
||||||
|
A []attribute `asn1:"set"`
|
||||||
|
}{A: attrs})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the leading sequence octets
|
||||||
|
var raw asn1.RawValue
|
||||||
|
asn1.Unmarshal(encodedAttributes, &raw)
|
||||||
|
return raw.Bytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type rawCertificates struct {
|
||||||
|
Raw asn1.RawContent
|
||||||
|
}
|
||||||
|
|
||||||
|
type issuerAndSerial struct {
|
||||||
|
IssuerName asn1.RawValue
|
||||||
|
SerialNumber *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDigestAlgorithm sets the digest algorithm to be used in the signing process.
|
||||||
|
//
|
||||||
|
// This should be called before adding signers
|
||||||
|
func (sd *SignedData) SetDigestAlgorithm(d asn1.ObjectIdentifier) {
|
||||||
|
sd.digestOid = d
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEncryptionAlgorithm sets the encryption algorithm to be used in the signing process.
|
||||||
|
//
|
||||||
|
// This should be called before adding signers
|
||||||
|
func (sd *SignedData) SetEncryptionAlgorithm(d asn1.ObjectIdentifier) {
|
||||||
|
sd.encryptionOid = d
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSigner is a wrapper around AddSignerChain() that adds a signer without any parent.
|
||||||
|
func (sd *SignedData) AddSigner(ee *x509.Certificate, pkey crypto.PrivateKey, config SignerInfoConfig) error {
|
||||||
|
var parents []*x509.Certificate
|
||||||
|
return sd.AddSignerChain(ee, pkey, parents, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSignerChain signs attributes about the content and adds certificates
|
||||||
|
// and signers infos to the Signed Data. The certificate and private key
|
||||||
|
// of the end-entity signer are used to issue the signature, and any
|
||||||
|
// parent of that end-entity that need to be added to the list of
|
||||||
|
// certifications can be specified in the parents slice.
|
||||||
|
//
|
||||||
|
// The signature algorithm used to hash the data is the one of the end-entity
|
||||||
|
// certificate.
|
||||||
|
func (sd *SignedData) AddSignerChain(ee *x509.Certificate, pkey crypto.PrivateKey, parents []*x509.Certificate, config SignerInfoConfig) error {
|
||||||
|
// Following RFC 2315, 9.2 SignerInfo type, the distinguished name of
|
||||||
|
// the issuer of the end-entity signer is stored in the issuerAndSerialNumber
|
||||||
|
// section of the SignedData.SignerInfo, alongside the serial number of
|
||||||
|
// the end-entity.
|
||||||
|
var ias issuerAndSerial
|
||||||
|
ias.SerialNumber = ee.SerialNumber
|
||||||
|
if len(parents) == 0 {
|
||||||
|
// no parent, the issuer is the end-entity cert itself
|
||||||
|
ias.IssuerName = asn1.RawValue{FullBytes: ee.RawIssuer}
|
||||||
|
} else {
|
||||||
|
err := verifyPartialChain(ee, parents)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// the first parent is the issuer
|
||||||
|
ias.IssuerName = asn1.RawValue{FullBytes: parents[0].RawSubject}
|
||||||
|
}
|
||||||
|
sd.sd.DigestAlgorithmIdentifiers = append(sd.sd.DigestAlgorithmIdentifiers,
|
||||||
|
pkix.AlgorithmIdentifier{Algorithm: sd.digestOid},
|
||||||
|
)
|
||||||
|
hash, err := getHashForOID(sd.digestOid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h := hash.New()
|
||||||
|
h.Write(sd.data)
|
||||||
|
sd.messageDigest = h.Sum(nil)
|
||||||
|
encryptionOid, err := getOIDForEncryptionAlgorithm(pkey, sd.digestOid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
attrs := &attributes{}
|
||||||
|
attrs.Add(OIDAttributeContentType, sd.sd.ContentInfo.ContentType)
|
||||||
|
attrs.Add(OIDAttributeMessageDigest, sd.messageDigest)
|
||||||
|
attrs.Add(OIDAttributeSigningTime, time.Now().UTC())
|
||||||
|
for _, attr := range config.ExtraSignedAttributes {
|
||||||
|
attrs.Add(attr.Type, attr.Value)
|
||||||
|
}
|
||||||
|
finalAttrs, err := attrs.ForMarshalling()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
unsignedAttrs := &attributes{}
|
||||||
|
for _, attr := range config.ExtraUnsignedAttributes {
|
||||||
|
unsignedAttrs.Add(attr.Type, attr.Value)
|
||||||
|
}
|
||||||
|
finalUnsignedAttrs, err := unsignedAttrs.ForMarshalling()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// create signature of signed attributes
|
||||||
|
signature, err := signAttributes(finalAttrs, pkey, hash)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
signer := signerInfo{
|
||||||
|
AuthenticatedAttributes: finalAttrs,
|
||||||
|
UnauthenticatedAttributes: finalUnsignedAttrs,
|
||||||
|
DigestAlgorithm: pkix.AlgorithmIdentifier{Algorithm: sd.digestOid},
|
||||||
|
DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: encryptionOid},
|
||||||
|
IssuerAndSerialNumber: ias,
|
||||||
|
EncryptedDigest: signature,
|
||||||
|
Version: 1,
|
||||||
|
}
|
||||||
|
sd.certs = append(sd.certs, ee)
|
||||||
|
if len(parents) > 0 {
|
||||||
|
sd.certs = append(sd.certs, parents...)
|
||||||
|
}
|
||||||
|
sd.sd.SignerInfos = append(sd.sd.SignerInfos, signer)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignWithoutAttr issues a signature on the content of the pkcs7 SignedData.
|
||||||
|
// Unlike AddSigner/AddSignerChain, it calculates the digest on the data alone
|
||||||
|
// and does not include any signed attributes like timestamp and so on.
|
||||||
|
//
|
||||||
|
// This function is needed to sign old Android APKs, something you probably
|
||||||
|
// shouldn't do unless you're maintaining backward compatibility for old
|
||||||
|
// applications.
|
||||||
|
func (sd *SignedData) SignWithoutAttr(ee *x509.Certificate, pkey crypto.PrivateKey, config SignerInfoConfig) error {
|
||||||
|
var signature []byte
|
||||||
|
sd.sd.DigestAlgorithmIdentifiers = append(sd.sd.DigestAlgorithmIdentifiers, pkix.AlgorithmIdentifier{Algorithm: sd.digestOid})
|
||||||
|
hash, err := getHashForOID(sd.digestOid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h := hash.New()
|
||||||
|
h.Write(sd.data)
|
||||||
|
sd.messageDigest = h.Sum(nil)
|
||||||
|
switch pkey := pkey.(type) {
|
||||||
|
case *dsa.PrivateKey:
|
||||||
|
// dsa doesn't implement crypto.Signer so we make a special case
|
||||||
|
// https://github.com/golang/go/issues/27889
|
||||||
|
r, s, err := dsa.Sign(rand.Reader, pkey, sd.messageDigest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
signature, err = asn1.Marshal(dsaSignature{r, s})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
key, ok := pkey.(crypto.Signer)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("pkcs7: private key does not implement crypto.Signer")
|
||||||
|
}
|
||||||
|
signature, err = key.Sign(rand.Reader, sd.messageDigest, hash)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var ias issuerAndSerial
|
||||||
|
ias.SerialNumber = ee.SerialNumber
|
||||||
|
// no parent, the issue is the end-entity cert itself
|
||||||
|
ias.IssuerName = asn1.RawValue{FullBytes: ee.RawIssuer}
|
||||||
|
if sd.encryptionOid == nil {
|
||||||
|
// if the encryption algorithm wasn't set by SetEncryptionAlgorithm,
|
||||||
|
// infer it from the digest algorithm
|
||||||
|
sd.encryptionOid, err = getOIDForEncryptionAlgorithm(pkey, sd.digestOid)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
signer := signerInfo{
|
||||||
|
DigestAlgorithm: pkix.AlgorithmIdentifier{Algorithm: sd.digestOid},
|
||||||
|
DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: sd.encryptionOid},
|
||||||
|
IssuerAndSerialNumber: ias,
|
||||||
|
EncryptedDigest: signature,
|
||||||
|
Version: 1,
|
||||||
|
}
|
||||||
|
// create signature of signed attributes
|
||||||
|
sd.certs = append(sd.certs, ee)
|
||||||
|
sd.sd.SignerInfos = append(sd.sd.SignerInfos, signer)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (si *signerInfo) SetUnauthenticatedAttributes(extraUnsignedAttrs []Attribute) error {
|
||||||
|
unsignedAttrs := &attributes{}
|
||||||
|
for _, attr := range extraUnsignedAttrs {
|
||||||
|
unsignedAttrs.Add(attr.Type, attr.Value)
|
||||||
|
}
|
||||||
|
finalUnsignedAttrs, err := unsignedAttrs.ForMarshalling()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
si.UnauthenticatedAttributes = finalUnsignedAttrs
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCertificate adds the certificate to the payload. Useful for parent certificates
|
||||||
|
func (sd *SignedData) AddCertificate(cert *x509.Certificate) {
|
||||||
|
sd.certs = append(sd.certs, cert)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detach removes content from the signed data struct to make it a detached signature.
|
||||||
|
// This must be called right before Finish()
|
||||||
|
func (sd *SignedData) Detach() {
|
||||||
|
sd.sd.ContentInfo = contentInfo{ContentType: OIDData}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSignedData returns the private Signed Data
|
||||||
|
func (sd *SignedData) GetSignedData() *signedData {
|
||||||
|
return &sd.sd
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish marshals the content and its signers
|
||||||
|
func (sd *SignedData) Finish() ([]byte, error) {
|
||||||
|
sd.sd.Certificates = marshalCertificates(sd.certs)
|
||||||
|
inner, err := asn1.Marshal(sd.sd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
outer := contentInfo{
|
||||||
|
ContentType: OIDSignedData,
|
||||||
|
Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: inner, IsCompound: true},
|
||||||
|
}
|
||||||
|
return asn1.Marshal(outer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAuthenticatedAttributes removes authenticated attributes from signedData
|
||||||
|
// similar to OpenSSL's PKCS7_NOATTR or -noattr flags
|
||||||
|
func (sd *SignedData) RemoveAuthenticatedAttributes() {
|
||||||
|
for i := range sd.sd.SignerInfos {
|
||||||
|
sd.sd.SignerInfos[i].AuthenticatedAttributes = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveUnauthenticatedAttributes removes unauthenticated attributes from signedData
|
||||||
|
func (sd *SignedData) RemoveUnauthenticatedAttributes() {
|
||||||
|
for i := range sd.sd.SignerInfos {
|
||||||
|
sd.sd.SignerInfos[i].UnauthenticatedAttributes = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyPartialChain checks that a given cert is issued by the first parent in the list,
|
||||||
|
// then continue down the path. It doesn't require the last parent to be a root CA,
|
||||||
|
// or to be trusted in any truststore. It simply verifies that the chain provided, albeit
|
||||||
|
// partial, makes sense.
|
||||||
|
func verifyPartialChain(cert *x509.Certificate, parents []*x509.Certificate) error {
|
||||||
|
if len(parents) == 0 {
|
||||||
|
return fmt.Errorf("pkcs7: zero parents provided to verify the signature of certificate %q", cert.Subject.CommonName)
|
||||||
|
}
|
||||||
|
err := cert.CheckSignatureFrom(parents[0])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("pkcs7: certificate signature from parent is invalid: %v", err)
|
||||||
|
}
|
||||||
|
if len(parents) == 1 {
|
||||||
|
// there is no more parent to check, return
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return verifyPartialChain(parents[0], parents[1:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func cert2issuerAndSerial(cert *x509.Certificate) (issuerAndSerial, error) {
|
||||||
|
var ias issuerAndSerial
|
||||||
|
// The issuer RDNSequence has to match exactly the sequence in the certificate
|
||||||
|
// We cannot use cert.Issuer.ToRDNSequence() here since it mangles the sequence
|
||||||
|
ias.IssuerName = asn1.RawValue{FullBytes: cert.RawIssuer}
|
||||||
|
ias.SerialNumber = cert.SerialNumber
|
||||||
|
|
||||||
|
return ias, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// signs the DER encoded form of the attributes with the private key
|
||||||
|
func signAttributes(attrs []attribute, pkey crypto.PrivateKey, digestAlg crypto.Hash) ([]byte, error) {
|
||||||
|
attrBytes, err := marshalAttributes(attrs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
h := digestAlg.New()
|
||||||
|
h.Write(attrBytes)
|
||||||
|
hash := h.Sum(nil)
|
||||||
|
|
||||||
|
// dsa doesn't implement crypto.Signer so we make a special case
|
||||||
|
// https://github.com/golang/go/issues/27889
|
||||||
|
switch pkey := pkey.(type) {
|
||||||
|
case *dsa.PrivateKey:
|
||||||
|
r, s, err := dsa.Sign(rand.Reader, pkey, hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return asn1.Marshal(dsaSignature{r, s})
|
||||||
|
}
|
||||||
|
|
||||||
|
key, ok := pkey.(crypto.Signer)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("pkcs7: private key does not implement crypto.Signer")
|
||||||
|
}
|
||||||
|
return key.Sign(rand.Reader, hash, digestAlg)
|
||||||
|
}
|
||||||
|
|
||||||
|
type dsaSignature struct {
|
||||||
|
R, S *big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
// concats and wraps the certificates in the RawValue structure
|
||||||
|
func marshalCertificates(certs []*x509.Certificate) rawCertificates {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for _, cert := range certs {
|
||||||
|
buf.Write(cert.Raw)
|
||||||
|
}
|
||||||
|
rawCerts, _ := marshalCertificateBytes(buf.Bytes())
|
||||||
|
return rawCerts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Even though, the tag & length are stripped out during marshalling the
|
||||||
|
// RawContent, we have to encode it into the RawContent. If its missing,
|
||||||
|
// then `asn1.Marshal()` will strip out the certificate wrapper instead.
|
||||||
|
func marshalCertificateBytes(certs []byte) (rawCertificates, error) {
|
||||||
|
var val = asn1.RawValue{Bytes: certs, Class: 2, Tag: 0, IsCompound: true}
|
||||||
|
b, err := asn1.Marshal(val)
|
||||||
|
if err != nil {
|
||||||
|
return rawCertificates{}, err
|
||||||
|
}
|
||||||
|
return rawCertificates{Raw: b}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DegenerateCertificate creates a signed data structure containing only the
|
||||||
|
// provided certificate or certificate chain.
|
||||||
|
func DegenerateCertificate(cert []byte) ([]byte, error) {
|
||||||
|
rawCert, err := marshalCertificateBytes(cert)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
emptyContent := contentInfo{ContentType: OIDData}
|
||||||
|
sd := signedData{
|
||||||
|
Version: 1,
|
||||||
|
ContentInfo: emptyContent,
|
||||||
|
Certificates: rawCert,
|
||||||
|
CRLs: []pkix.CertificateList{},
|
||||||
|
}
|
||||||
|
content, err := asn1.Marshal(sd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
signedContent := contentInfo{
|
||||||
|
ContentType: OIDSignedData,
|
||||||
|
Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true},
|
||||||
|
}
|
||||||
|
return asn1.Marshal(signedContent)
|
||||||
|
}
|
264
vendor/go.mozilla.org/pkcs7/verify.go
generated
vendored
Normal file
264
vendor/go.mozilla.org/pkcs7/verify.go
generated
vendored
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
package pkcs7
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/asn1"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Verify is a wrapper around VerifyWithChain() that initializes an empty
|
||||||
|
// trust store, effectively disabling certificate verification when validating
|
||||||
|
// a signature.
|
||||||
|
func (p7 *PKCS7) Verify() (err error) {
|
||||||
|
return p7.VerifyWithChain(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyWithChain checks the signatures of a PKCS7 object.
|
||||||
|
// If truststore is not nil, it also verifies the chain of trust of the end-entity
|
||||||
|
// signer cert to one of the root in the truststore.
|
||||||
|
func (p7 *PKCS7) VerifyWithChain(truststore *x509.CertPool) (err error) {
|
||||||
|
if len(p7.Signers) == 0 {
|
||||||
|
return errors.New("pkcs7: Message has no signers")
|
||||||
|
}
|
||||||
|
for _, signer := range p7.Signers {
|
||||||
|
if err := verifySignature(p7, signer, truststore); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifySignature(p7 *PKCS7, signer signerInfo, truststore *x509.CertPool) (err error) {
|
||||||
|
signedData := p7.Content
|
||||||
|
ee := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
|
||||||
|
if ee == nil {
|
||||||
|
return errors.New("pkcs7: No certificate for signer")
|
||||||
|
}
|
||||||
|
signingTime := time.Now().UTC()
|
||||||
|
if len(signer.AuthenticatedAttributes) > 0 {
|
||||||
|
// TODO(fullsailor): First check the content type match
|
||||||
|
var digest []byte
|
||||||
|
err := unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeMessageDigest, &digest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hash, err := getHashForOID(signer.DigestAlgorithm.Algorithm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h := hash.New()
|
||||||
|
h.Write(p7.Content)
|
||||||
|
computed := h.Sum(nil)
|
||||||
|
if subtle.ConstantTimeCompare(digest, computed) != 1 {
|
||||||
|
return &MessageDigestMismatchError{
|
||||||
|
ExpectedDigest: digest,
|
||||||
|
ActualDigest: computed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
signedData, err = marshalAttributes(signer.AuthenticatedAttributes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = unmarshalAttribute(signer.AuthenticatedAttributes, OIDAttributeSigningTime, &signingTime)
|
||||||
|
if err == nil {
|
||||||
|
// signing time found, performing validity check
|
||||||
|
if signingTime.After(ee.NotAfter) || signingTime.Before(ee.NotBefore) {
|
||||||
|
return fmt.Errorf("pkcs7: signing time %q is outside of certificate validity %q to %q",
|
||||||
|
signingTime.Format(time.RFC3339),
|
||||||
|
ee.NotBefore.Format(time.RFC3339),
|
||||||
|
ee.NotBefore.Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if truststore != nil {
|
||||||
|
_, err = verifyCertChain(ee, p7.Certificates, truststore, signingTime)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sigalg, err := getSignatureAlgorithm(signer.DigestEncryptionAlgorithm, signer.DigestAlgorithm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ee.CheckSignature(sigalg, signedData, signer.EncryptedDigest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOnlySigner returns an x509.Certificate for the first signer of the signed
|
||||||
|
// data payload. If there are more or less than one signer, nil is returned
|
||||||
|
func (p7 *PKCS7) GetOnlySigner() *x509.Certificate {
|
||||||
|
if len(p7.Signers) != 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
signer := p7.Signers[0]
|
||||||
|
return getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalSignedAttribute decodes a single attribute from the signer info
|
||||||
|
func (p7 *PKCS7) UnmarshalSignedAttribute(attributeType asn1.ObjectIdentifier, out interface{}) error {
|
||||||
|
sd, ok := p7.raw.(signedData)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("pkcs7: payload is not signedData content")
|
||||||
|
}
|
||||||
|
if len(sd.SignerInfos) < 1 {
|
||||||
|
return errors.New("pkcs7: payload has no signers")
|
||||||
|
}
|
||||||
|
attributes := sd.SignerInfos[0].AuthenticatedAttributes
|
||||||
|
return unmarshalAttribute(attributes, attributeType, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSignedData(data []byte) (*PKCS7, error) {
|
||||||
|
var sd signedData
|
||||||
|
asn1.Unmarshal(data, &sd)
|
||||||
|
certs, err := sd.Certificates.Parse()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// fmt.Printf("--> Signed Data Version %d\n", sd.Version)
|
||||||
|
|
||||||
|
var compound asn1.RawValue
|
||||||
|
var content unsignedData
|
||||||
|
|
||||||
|
// The Content.Bytes maybe empty on PKI responses.
|
||||||
|
if len(sd.ContentInfo.Content.Bytes) > 0 {
|
||||||
|
if _, err := asn1.Unmarshal(sd.ContentInfo.Content.Bytes, &compound); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Compound octet string
|
||||||
|
if compound.IsCompound {
|
||||||
|
if compound.Tag == 4 {
|
||||||
|
if _, err = asn1.Unmarshal(compound.Bytes, &content); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
content = compound.Bytes
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// assuming this is tag 04
|
||||||
|
content = compound.Bytes
|
||||||
|
}
|
||||||
|
return &PKCS7{
|
||||||
|
Content: content,
|
||||||
|
Certificates: certs,
|
||||||
|
CRLs: sd.CRLs,
|
||||||
|
Signers: sd.SignerInfos,
|
||||||
|
raw: sd}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyCertChain takes an end-entity certs, a list of potential intermediates and a
|
||||||
|
// truststore, and built all potential chains between the EE and a trusted root.
|
||||||
|
//
|
||||||
|
// When verifying chains that may have expired, currentTime can be set to a past date
|
||||||
|
// to allow the verification to pass. If unset, currentTime is set to the current UTC time.
|
||||||
|
func verifyCertChain(ee *x509.Certificate, certs []*x509.Certificate, truststore *x509.CertPool, currentTime time.Time) (chains [][]*x509.Certificate, err error) {
|
||||||
|
intermediates := x509.NewCertPool()
|
||||||
|
for _, intermediate := range certs {
|
||||||
|
intermediates.AddCert(intermediate)
|
||||||
|
}
|
||||||
|
verifyOptions := x509.VerifyOptions{
|
||||||
|
Roots: truststore,
|
||||||
|
Intermediates: intermediates,
|
||||||
|
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
|
||||||
|
CurrentTime: currentTime,
|
||||||
|
}
|
||||||
|
chains, err = ee.Verify(verifyOptions)
|
||||||
|
if err != nil {
|
||||||
|
return chains, fmt.Errorf("pkcs7: failed to verify certificate chain: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageDigestMismatchError is returned when the signer data digest does not
|
||||||
|
// match the computed digest for the contained content
|
||||||
|
type MessageDigestMismatchError struct {
|
||||||
|
ExpectedDigest []byte
|
||||||
|
ActualDigest []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err *MessageDigestMismatchError) Error() string {
|
||||||
|
return fmt.Sprintf("pkcs7: Message digest mismatch\n\tExpected: %X\n\tActual : %X", err.ExpectedDigest, err.ActualDigest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSignatureAlgorithm(digestEncryption, digest pkix.AlgorithmIdentifier) (x509.SignatureAlgorithm, error) {
|
||||||
|
switch {
|
||||||
|
case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA1):
|
||||||
|
return x509.ECDSAWithSHA1, nil
|
||||||
|
case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA256):
|
||||||
|
return x509.ECDSAWithSHA256, nil
|
||||||
|
case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA384):
|
||||||
|
return x509.ECDSAWithSHA384, nil
|
||||||
|
case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmECDSASHA512):
|
||||||
|
return x509.ECDSAWithSHA512, nil
|
||||||
|
case digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSA),
|
||||||
|
digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA1),
|
||||||
|
digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA256),
|
||||||
|
digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA384),
|
||||||
|
digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmRSASHA512):
|
||||||
|
switch {
|
||||||
|
case digest.Algorithm.Equal(OIDDigestAlgorithmSHA1):
|
||||||
|
return x509.SHA1WithRSA, nil
|
||||||
|
case digest.Algorithm.Equal(OIDDigestAlgorithmSHA256):
|
||||||
|
return x509.SHA256WithRSA, nil
|
||||||
|
case digest.Algorithm.Equal(OIDDigestAlgorithmSHA384):
|
||||||
|
return x509.SHA384WithRSA, nil
|
||||||
|
case digest.Algorithm.Equal(OIDDigestAlgorithmSHA512):
|
||||||
|
return x509.SHA512WithRSA, nil
|
||||||
|
default:
|
||||||
|
return -1, fmt.Errorf("pkcs7: unsupported digest %q for encryption algorithm %q",
|
||||||
|
digest.Algorithm.String(), digestEncryption.Algorithm.String())
|
||||||
|
}
|
||||||
|
case digestEncryption.Algorithm.Equal(OIDDigestAlgorithmDSA),
|
||||||
|
digestEncryption.Algorithm.Equal(OIDDigestAlgorithmDSASHA1):
|
||||||
|
switch {
|
||||||
|
case digest.Algorithm.Equal(OIDDigestAlgorithmSHA1):
|
||||||
|
return x509.DSAWithSHA1, nil
|
||||||
|
case digest.Algorithm.Equal(OIDDigestAlgorithmSHA256):
|
||||||
|
return x509.DSAWithSHA256, nil
|
||||||
|
default:
|
||||||
|
return -1, fmt.Errorf("pkcs7: unsupported digest %q for encryption algorithm %q",
|
||||||
|
digest.Algorithm.String(), digestEncryption.Algorithm.String())
|
||||||
|
}
|
||||||
|
case digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmECDSAP256),
|
||||||
|
digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmECDSAP384),
|
||||||
|
digestEncryption.Algorithm.Equal(OIDEncryptionAlgorithmECDSAP521):
|
||||||
|
switch {
|
||||||
|
case digest.Algorithm.Equal(OIDDigestAlgorithmSHA1):
|
||||||
|
return x509.ECDSAWithSHA1, nil
|
||||||
|
case digest.Algorithm.Equal(OIDDigestAlgorithmSHA256):
|
||||||
|
return x509.ECDSAWithSHA256, nil
|
||||||
|
case digest.Algorithm.Equal(OIDDigestAlgorithmSHA384):
|
||||||
|
return x509.ECDSAWithSHA384, nil
|
||||||
|
case digest.Algorithm.Equal(OIDDigestAlgorithmSHA512):
|
||||||
|
return x509.ECDSAWithSHA512, nil
|
||||||
|
default:
|
||||||
|
return -1, fmt.Errorf("pkcs7: unsupported digest %q for encryption algorithm %q",
|
||||||
|
digest.Algorithm.String(), digestEncryption.Algorithm.String())
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return -1, fmt.Errorf("pkcs7: unsupported algorithm %q",
|
||||||
|
digestEncryption.Algorithm.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCertFromCertsByIssuerAndSerial(certs []*x509.Certificate, ias issuerAndSerial) *x509.Certificate {
|
||||||
|
for _, cert := range certs {
|
||||||
|
if isCertMatchForIssuerAndSerial(cert, ias) {
|
||||||
|
return cert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalAttribute(attrs []attribute, attributeType asn1.ObjectIdentifier, out interface{}) error {
|
||||||
|
for _, attr := range attrs {
|
||||||
|
if attr.Type.Equal(attributeType) {
|
||||||
|
_, err := asn1.Unmarshal(attr.Value.Bytes, out)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.New("pkcs7: attribute type not in attributes")
|
||||||
|
}
|
8
vendor/modules.txt
vendored
8
vendor/modules.txt
vendored
@ -66,7 +66,7 @@ github.com/containernetworking/plugins/pkg/utils/hwaddr
|
|||||||
github.com/containernetworking/plugins/pkg/utils/sysctl
|
github.com/containernetworking/plugins/pkg/utils/sysctl
|
||||||
github.com/containernetworking/plugins/plugins/ipam/host-local/backend
|
github.com/containernetworking/plugins/plugins/ipam/host-local/backend
|
||||||
github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator
|
github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator
|
||||||
# github.com/containers/buildah v1.15.1-0.20200708111410-d2ea9429455d
|
# github.com/containers/buildah v1.15.1-0.20200731151214-29f4d01c621c
|
||||||
github.com/containers/buildah
|
github.com/containers/buildah
|
||||||
github.com/containers/buildah/bind
|
github.com/containers/buildah/bind
|
||||||
github.com/containers/buildah/chroot
|
github.com/containers/buildah/chroot
|
||||||
@ -137,7 +137,7 @@ github.com/containers/image/v5/types
|
|||||||
github.com/containers/image/v5/version
|
github.com/containers/image/v5/version
|
||||||
# github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b
|
# github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b
|
||||||
github.com/containers/libtrust
|
github.com/containers/libtrust
|
||||||
# github.com/containers/ocicrypt v1.0.2
|
# github.com/containers/ocicrypt v1.0.3
|
||||||
github.com/containers/ocicrypt
|
github.com/containers/ocicrypt
|
||||||
github.com/containers/ocicrypt/blockcipher
|
github.com/containers/ocicrypt/blockcipher
|
||||||
github.com/containers/ocicrypt/config
|
github.com/containers/ocicrypt/config
|
||||||
@ -279,8 +279,6 @@ github.com/docker/spdystream/spdy
|
|||||||
github.com/fsnotify/fsnotify
|
github.com/fsnotify/fsnotify
|
||||||
# github.com/fsouza/go-dockerclient v1.6.5
|
# github.com/fsouza/go-dockerclient v1.6.5
|
||||||
github.com/fsouza/go-dockerclient
|
github.com/fsouza/go-dockerclient
|
||||||
# github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa
|
|
||||||
github.com/fullsailor/pkcs7
|
|
||||||
# github.com/ghodss/yaml v1.0.0
|
# github.com/ghodss/yaml v1.0.0
|
||||||
github.com/ghodss/yaml
|
github.com/ghodss/yaml
|
||||||
# github.com/godbus/dbus/v5 v5.0.3
|
# github.com/godbus/dbus/v5 v5.0.3
|
||||||
@ -554,6 +552,8 @@ github.com/xeipuuv/gojsonreference
|
|||||||
github.com/xeipuuv/gojsonschema
|
github.com/xeipuuv/gojsonschema
|
||||||
# go.etcd.io/bbolt v1.3.5
|
# go.etcd.io/bbolt v1.3.5
|
||||||
go.etcd.io/bbolt
|
go.etcd.io/bbolt
|
||||||
|
# go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1
|
||||||
|
go.mozilla.org/pkcs7
|
||||||
# go.opencensus.io v0.22.0
|
# go.opencensus.io v0.22.0
|
||||||
go.opencensus.io
|
go.opencensus.io
|
||||||
go.opencensus.io/internal
|
go.opencensus.io/internal
|
||||||
|
Reference in New Issue
Block a user