Compare commits
68 Commits
Author | SHA1 | Date |
---|---|---|
|
c8950a22ff | |
|
2effa14651 | |
|
05f73b6eb9 | |
|
425f26530b | |
|
fa29bf69b3 | |
|
587b27f5ec | |
|
cc226893c8 | |
|
94907715d1 | |
|
1db71af9f2 | |
|
45fc0b168f | |
|
3d7fc3f394 | |
|
0b88532006 | |
|
809cd12df5 | |
|
e26515dd4d | |
|
0703ce7589 | |
|
7d0db7295f | |
|
5221197f44 | |
|
c4489465a6 | |
|
30c2fb6a4b | |
|
f840ae296f | |
|
ccaf1f86ed | |
|
4b2101afac | |
|
c430e43c76 | |
|
a24b47713b | |
|
c0e1fd5b82 | |
|
f98af7c91e | |
|
526c1bdfb8 | |
|
5574f24ad7 | |
|
bd5c1167aa | |
|
ffc163c18e | |
|
804a61fab1 | |
|
be20dcb008 | |
|
26329d2083 | |
|
34c2da3cd2 | |
|
8e82f71d81 | |
|
cee08c60cc | |
|
01784fe70f | |
|
3526ded5df | |
|
5e79dd9733 | |
|
c1e4d5e5d4 | |
|
c60342cfb9 | |
|
19b5c83b3e | |
|
441f499c8d | |
|
23f8351694 | |
|
ee4e19a2ec | |
|
e0cec6f7be | |
|
e2217b9802 | |
|
2e2562f758 | |
|
032bb592f0 | |
|
aabe8c651a | |
|
f1528dcdfe | |
|
b0e73385d6 | |
|
5d9a3f4315 | |
|
eb576cec58 | |
|
1957e81544 | |
|
6e1e0cfa0f | |
|
da960c9d0c | |
|
8db256161d | |
|
09110029c2 | |
|
d7b43ce446 | |
|
e999b44ae0 | |
|
7f587f7a03 | |
|
b1a0a10291 | |
|
c61dfa5ee6 | |
|
b2b6a741b1 | |
|
b2e09cde6d | |
|
a468e1acd8 | |
|
c6959172c1 |
|
@ -0,0 +1,74 @@
|
||||||
|
# For most projects, this workflow file will not need changing; you simply need
|
||||||
|
# to commit it to your repository.
|
||||||
|
#
|
||||||
|
# You may wish to alter this file to override the set of languages analyzed,
|
||||||
|
# or to provide custom queries or build logic.
|
||||||
|
#
|
||||||
|
# ******** NOTE ********
|
||||||
|
# We have attempted to detect the languages in your repository. Please check
|
||||||
|
# the `language` matrix defined below to confirm you have the correct set of
|
||||||
|
# supported CodeQL languages.
|
||||||
|
#
|
||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ "main" ]
|
||||||
|
schedule:
|
||||||
|
- cron: '00 10 1 * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'go' ]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
|
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
|
||||||
|
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||||
|
# queries: security-extended,security-and-quality
|
||||||
|
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v2
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
|
|
||||||
|
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||||
|
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||||
|
|
||||||
|
# - run: |
|
||||||
|
# echo "Run, Build Application using script"
|
||||||
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
with:
|
||||||
|
category: "/language:${{matrix.language}}"
|
|
@ -0,0 +1,40 @@
|
||||||
|
name: Go
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "main" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "main" ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go: [ '1.24', '1.23' ]
|
||||||
|
name: Go Version ${{ matrix.go }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install deps
|
||||||
|
run: |
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get install -y gnutls-bin softhsm2
|
||||||
|
|
||||||
|
- name: Setup go
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go }}
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.0.1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Run golangci-lint
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: make test
|
|
@ -0,0 +1 @@
|
||||||
|
*~
|
|
@ -0,0 +1,47 @@
|
||||||
|
version: "2"
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- depguard
|
||||||
|
- misspell
|
||||||
|
- revive
|
||||||
|
- unconvert
|
||||||
|
settings:
|
||||||
|
depguard:
|
||||||
|
rules:
|
||||||
|
main:
|
||||||
|
files:
|
||||||
|
- $all
|
||||||
|
deny:
|
||||||
|
- pkg: io/ioutil
|
||||||
|
revive:
|
||||||
|
severity: error
|
||||||
|
rules:
|
||||||
|
- name: indent-error-flow
|
||||||
|
severity: warning
|
||||||
|
disabled: false
|
||||||
|
- name: error-strings
|
||||||
|
disabled: false
|
||||||
|
staticcheck:
|
||||||
|
checks:
|
||||||
|
- -SA1019
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
presets:
|
||||||
|
- comments
|
||||||
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
- std-error-handling
|
||||||
|
paths:
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
paths:
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
29
.travis.yml
29
.travis.yml
|
@ -1,29 +0,0 @@
|
||||||
dist: bionic
|
|
||||||
language: go
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
|
|
||||||
go:
|
|
||||||
- "1.13.x"
|
|
||||||
- "1.16.x"
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: linux
|
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- gnutls-bin
|
|
||||||
- softhsm2
|
|
||||||
|
|
||||||
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.30.0
|
|
||||||
|
|
||||||
script:
|
|
||||||
- make
|
|
||||||
- make check
|
|
||||||
- make test
|
|
|
@ -1,3 +1,3 @@
|
||||||
## The OCIcrypt Library Project Community Code of Conduct
|
## The OCIcrypt Library Project Community Code of Conduct
|
||||||
|
|
||||||
The OCIcrypt Library project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md).
|
The OCIcrypt Library project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/main/CODE-OF-CONDUCT.md).
|
||||||
|
|
1
Makefile
1
Makefile
|
@ -28,6 +28,7 @@ vendor:
|
||||||
go mod tidy
|
go mod tidy
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
go clean -testcache
|
||||||
go test ./... -test.v
|
go test ./... -test.v
|
||||||
|
|
||||||
generate-protobuf:
|
generate-protobuf:
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
## Security and Disclosure Information Policy for the OCIcrypt Library Project
|
## 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.
|
The OCIcrypt Library Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/main/SECURITY.md) for the Containers Projects.
|
||||||
|
|
|
@ -17,10 +17,11 @@
|
||||||
package blockcipher
|
package blockcipher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// LayerCipherType is the ciphertype as specified in the layer metadata
|
// LayerCipherType is the ciphertype as specified in the layer metadata
|
||||||
|
@ -95,9 +96,8 @@ func (lbco LayerBlockCipherOptions) GetOpt(key string) (value []byte, ok bool) {
|
||||||
return v, ok
|
return v, ok
|
||||||
} else if v, ok := lbco.Private.CipherOptions[key]; ok {
|
} else if v, ok := lbco.Private.CipherOptions[key]; ok {
|
||||||
return v, ok
|
return v, ok
|
||||||
} else {
|
|
||||||
return nil, false
|
|
||||||
}
|
}
|
||||||
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func wrapFinalizerWithType(fin Finalizer, typ LayerCipherType) Finalizer {
|
func wrapFinalizerWithType(fin Finalizer, typ LayerCipherType) Finalizer {
|
||||||
|
@ -129,7 +129,7 @@ func (h *LayerBlockCipherHandler) Encrypt(plainDataReader io.Reader, typ LayerCi
|
||||||
}
|
}
|
||||||
return encDataReader, fin, err
|
return encDataReader, fin, err
|
||||||
}
|
}
|
||||||
return nil, nil, errors.Errorf("unsupported cipher type: %s", typ)
|
return nil, nil, fmt.Errorf("unsupported cipher type: %s", typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt is the handler for the layer decryption routine
|
// Decrypt is the handler for the layer decryption routine
|
||||||
|
@ -138,10 +138,10 @@ func (h *LayerBlockCipherHandler) Decrypt(encDataReader io.Reader, opt LayerBloc
|
||||||
if typ == "" {
|
if typ == "" {
|
||||||
return nil, LayerBlockCipherOptions{}, errors.New("no cipher type provided")
|
return nil, LayerBlockCipherOptions{}, errors.New("no cipher type provided")
|
||||||
}
|
}
|
||||||
if c, ok := h.cipherMap[LayerCipherType(typ)]; ok {
|
if c, ok := h.cipherMap[typ]; ok {
|
||||||
return c.Decrypt(encDataReader, opt)
|
return c.Decrypt(encDataReader, opt)
|
||||||
}
|
}
|
||||||
return nil, LayerBlockCipherOptions{}, errors.Errorf("unsupported cipher type: %s", typ)
|
return nil, LayerBlockCipherOptions{}, fmt.Errorf("unsupported cipher type: %s", typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLayerBlockCipherHandler returns a new default handler
|
// NewLayerBlockCipherHandler returns a new default handler
|
||||||
|
@ -153,7 +153,7 @@ func NewLayerBlockCipherHandler() (*LayerBlockCipherHandler, error) {
|
||||||
var err error
|
var err error
|
||||||
h.cipherMap[AES256CTR], err = NewAESCTRLayerBlockCipher(256)
|
h.cipherMap[AES256CTR], err = NewAESCTRLayerBlockCipher(256)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "unable to set up Cipher AES-256-CTR")
|
return nil, fmt.Errorf("unable to set up Cipher AES-256-CTR: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &h, nil
|
return &h, nil
|
||||||
|
|
|
@ -22,12 +22,12 @@ import (
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/containers/ocicrypt/utils"
|
"github.com/containers/ocicrypt/utils"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AESCTRLayerBlockCipher implements the AES CTR stream cipher
|
// AESCTRLayerBlockCipher implements the AES CTR stream cipher
|
||||||
|
@ -74,7 +74,7 @@ func (r *aesctrcryptor) Read(p []byte) (int, error) {
|
||||||
|
|
||||||
if !r.bc.encrypt {
|
if !r.bc.encrypt {
|
||||||
if _, err := r.bc.hmac.Write(p[:o]); err != nil {
|
if _, err := r.bc.hmac.Write(p[:o]); err != nil {
|
||||||
r.bc.err = errors.Wrapf(err, "could not write to hmac")
|
r.bc.err = fmt.Errorf("could not write to hmac: %w", err)
|
||||||
return 0, r.bc.err
|
return 0, r.bc.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ func (r *aesctrcryptor) Read(p []byte) (int, error) {
|
||||||
|
|
||||||
if r.bc.encrypt {
|
if r.bc.encrypt {
|
||||||
if _, err := r.bc.hmac.Write(p[:o]); err != nil {
|
if _, err := r.bc.hmac.Write(p[:o]); err != nil {
|
||||||
r.bc.err = errors.Wrapf(err, "could not write to hmac")
|
r.bc.err = fmt.Errorf("could not write to hmac: %w", err)
|
||||||
return 0, r.bc.err
|
return 0, r.bc.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,13 +120,13 @@ func (bc *AESCTRLayerBlockCipher) init(encrypt bool, reader io.Reader, opts Laye
|
||||||
if !ok {
|
if !ok {
|
||||||
nonce = make([]byte, aes.BlockSize)
|
nonce = make([]byte, aes.BlockSize)
|
||||||
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
||||||
return LayerBlockCipherOptions{}, errors.Wrap(err, "unable to generate random nonce")
|
return LayerBlockCipherOptions{}, fmt.Errorf("unable to generate random nonce: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
block, err := aes.NewCipher(key)
|
block, err := aes.NewCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return LayerBlockCipherOptions{}, errors.Wrap(err, "aes.NewCipher failed")
|
return LayerBlockCipherOptions{}, fmt.Errorf("aes.NewCipher failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
bc.reader = reader
|
bc.reader = reader
|
||||||
|
|
|
@ -17,11 +17,12 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containers/ocicrypt/crypto/pkcs11"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/containers/ocicrypt/crypto/pkcs11"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EncryptWithJwe returns a CryptoConfig to encrypt with jwe public keys
|
// EncryptWithJwe returns a CryptoConfig to encrypt with jwe public keys
|
||||||
|
@ -85,7 +86,7 @@ func EncryptWithPkcs11(pkcs11Config *pkcs11.Pkcs11Config, pkcs11Pubkeys, pkcs11Y
|
||||||
}
|
}
|
||||||
p11confYaml, err := yaml.Marshal(pkcs11Config)
|
p11confYaml, err := yaml.Marshal(pkcs11Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return CryptoConfig{}, errors.Wrapf(err, "Could not marshal Pkcs11Config to Yaml")
|
return CryptoConfig{}, fmt.Errorf("Could not marshal Pkcs11Config to Yaml: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dc = DecryptConfig{
|
dc = DecryptConfig{
|
||||||
|
@ -223,7 +224,7 @@ func DecryptWithGpgPrivKeys(gpgPrivKeys, gpgPrivKeysPwds [][]byte) (CryptoConfig
|
||||||
func DecryptWithPkcs11Yaml(pkcs11Config *pkcs11.Pkcs11Config, pkcs11Yamls [][]byte) (CryptoConfig, error) {
|
func DecryptWithPkcs11Yaml(pkcs11Config *pkcs11.Pkcs11Config, pkcs11Yamls [][]byte) (CryptoConfig, error) {
|
||||||
p11confYaml, err := yaml.Marshal(pkcs11Config)
|
p11confYaml, err := yaml.Marshal(pkcs11Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return CryptoConfig{}, errors.Wrapf(err, "Could not marshal Pkcs11Config to Yaml")
|
return CryptoConfig{}, fmt.Errorf("Could not marshal Pkcs11Config to Yaml: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dc := DecryptConfig{
|
dc := DecryptConfig{
|
||||||
|
|
|
@ -18,8 +18,7 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/pkg/errors"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,7 +51,7 @@ func parseConfigFile(filename string) (*OcicryptConfig, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(filename)
|
data, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -72,7 +71,7 @@ func GetConfiguration() (*OcicryptConfig, error) {
|
||||||
if len(filename) > 0 {
|
if len(filename) > 0 {
|
||||||
ic, err = parseConfigFile(filename)
|
ic, err = parseConfigFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Error while parsing keyprovider config file")
|
return nil, fmt.Errorf("Error while parsing keyprovider config file: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -17,14 +17,13 @@
|
||||||
package pkcs11config
|
package pkcs11config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"github.com/containers/ocicrypt/crypto/pkcs11"
|
"github.com/containers/ocicrypt/crypto/pkcs11"
|
||||||
"github.com/pkg/errors"
|
"gopkg.in/yaml.v3"
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// OcicryptConfig represents the format of an imgcrypt.conf config file
|
// OcicryptConfig represents the format of an imgcrypt.conf config file
|
||||||
|
@ -39,11 +38,11 @@ const ENVVARNAME = "OCICRYPT_CONFIG"
|
||||||
// not exist, so no error is returned.
|
// not exist, so no error is returned.
|
||||||
// A config file may look like this:
|
// A config file may look like this:
|
||||||
// module-directories:
|
// module-directories:
|
||||||
// - /usr/lib64/pkcs11/
|
// - /usr/lib64/pkcs11/
|
||||||
// - /usr/lib/pkcs11/
|
// - /usr/lib/pkcs11/
|
||||||
// allowed-module-paths:
|
// allowed-module-paths:
|
||||||
// - /usr/lib64/pkcs11/
|
// - /usr/lib64/pkcs11/
|
||||||
// - /usr/lib/pkcs11/
|
// - /usr/lib/pkcs11/
|
||||||
func parseConfigFile(filename string) (*OcicryptConfig, error) {
|
func parseConfigFile(filename string) (*OcicryptConfig, error) {
|
||||||
// a non-existent config file is not an error
|
// a non-existent config file is not an error
|
||||||
_, err := os.Stat(filename)
|
_, err := os.Stat(filename)
|
||||||
|
@ -51,7 +50,7 @@ func parseConfigFile(filename string) (*OcicryptConfig, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(filename)
|
data, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@ package pkcs11
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
pkcs11uri "github.com/stefanberger/go-pkcs11uri"
|
pkcs11uri "github.com/stefanberger/go-pkcs11uri"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pkcs11KeyFile describes the format of the pkcs11 (private) key file.
|
// Pkcs11KeyFile describes the format of the pkcs11 (private) key file.
|
||||||
|
@ -42,7 +42,7 @@ func ParsePkcs11Uri(uri string) (*pkcs11uri.Pkcs11URI, error) {
|
||||||
p11uri := pkcs11uri.New()
|
p11uri := pkcs11uri.New()
|
||||||
err := p11uri.Parse(uri)
|
err := p11uri.Parse(uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "Could not parse Pkcs11URI from file")
|
return nil, fmt.Errorf("Could not parse Pkcs11URI from file: %w", err)
|
||||||
}
|
}
|
||||||
return p11uri, err
|
return p11uri, err
|
||||||
}
|
}
|
||||||
|
@ -50,14 +50,14 @@ func ParsePkcs11Uri(uri string) (*pkcs11uri.Pkcs11URI, error) {
|
||||||
// ParsePkcs11KeyFile parses a pkcs11 key file holding a pkcs11 URI describing a private key.
|
// ParsePkcs11KeyFile parses a pkcs11 key file holding a pkcs11 URI describing a private key.
|
||||||
// The file has the following yaml format:
|
// The file has the following yaml format:
|
||||||
// pkcs11:
|
// pkcs11:
|
||||||
// - uri : <pkcs11 uri>
|
// - uri : <pkcs11 uri>
|
||||||
// An error is returned if the pkcs11 URI is malformed
|
// An error is returned if the pkcs11 URI is malformed
|
||||||
func ParsePkcs11KeyFile(yamlstr []byte) (*Pkcs11KeyFileObject, error) {
|
func ParsePkcs11KeyFile(yamlstr []byte) (*Pkcs11KeyFileObject, error) {
|
||||||
p11keyfile := Pkcs11KeyFile{}
|
p11keyfile := Pkcs11KeyFile{}
|
||||||
|
|
||||||
err := yaml.Unmarshal([]byte(yamlstr), &p11keyfile)
|
err := yaml.Unmarshal(yamlstr, &p11keyfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "Could not unmarshal pkcs11 keyfile")
|
return nil, fmt.Errorf("Could not unmarshal pkcs11 keyfile: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
p11uri, err := ParsePkcs11Uri(p11keyfile.Pkcs11.Uri)
|
p11uri, err := ParsePkcs11Uri(p11keyfile.Pkcs11.Uri)
|
||||||
|
@ -102,7 +102,7 @@ func GetDefaultModuleDirectories() []string {
|
||||||
"/usr/lib/softhsm/", // Debian,Ubuntu
|
"/usr/lib/softhsm/", // Debian,Ubuntu
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debian directory: /usr/lib/(x86_64|aarch64|arm|powerpc64le|s390x)-linux-gnu/
|
// Debian directory: /usr/lib/(x86_64|aarch64|arm|powerpc64le|riscv64|s390x)-linux-gnu/
|
||||||
hosttype, ostype, q := getHostAndOsType()
|
hosttype, ostype, q := getHostAndOsType()
|
||||||
if len(hosttype) > 0 {
|
if len(hosttype) > 0 {
|
||||||
dir := fmt.Sprintf("/usr/lib/%s-%s-%s/", hosttype, ostype, q)
|
dir := fmt.Sprintf("/usr/lib/%s-%s-%s/", hosttype, ostype, q)
|
||||||
|
@ -126,9 +126,9 @@ func GetDefaultModuleDirectoriesYaml(indent string) string {
|
||||||
func ParsePkcs11ConfigFile(yamlstr []byte) (*Pkcs11Config, error) {
|
func ParsePkcs11ConfigFile(yamlstr []byte) (*Pkcs11Config, error) {
|
||||||
p11conf := Pkcs11Config{}
|
p11conf := Pkcs11Config{}
|
||||||
|
|
||||||
err := yaml.Unmarshal([]byte(yamlstr), &p11conf)
|
err := yaml.Unmarshal(yamlstr, &p11conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &p11conf, errors.Wrapf(err, "Could not parse Pkcs11Config")
|
return &p11conf, fmt.Errorf("Could not parse Pkcs11Config: %w", err)
|
||||||
}
|
}
|
||||||
return &p11conf, nil
|
return &p11conf, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build cgo
|
||||||
// +build cgo
|
// +build cgo
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -25,6 +26,7 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -33,7 +35,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/miekg/pkcs11"
|
"github.com/miekg/pkcs11"
|
||||||
"github.com/pkg/errors"
|
|
||||||
pkcs11uri "github.com/stefanberger/go-pkcs11uri"
|
pkcs11uri "github.com/stefanberger/go-pkcs11uri"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -76,11 +77,11 @@ func rsaPublicEncryptOAEP(pubKey *rsa.PublicKey, plaintext []byte) ([]byte, stri
|
||||||
hashfunc = sha256.New()
|
hashfunc = sha256.New()
|
||||||
hashalg = "sha256"
|
hashalg = "sha256"
|
||||||
default:
|
default:
|
||||||
return nil, "", errors.Errorf("Unsupported OAEP hash '%s'", oaephash)
|
return nil, "", fmt.Errorf("Unsupported OAEP hash '%s'", oaephash)
|
||||||
}
|
}
|
||||||
ciphertext, err := rsa.EncryptOAEP(hashfunc, rand.Reader, pubKey, plaintext, OAEPLabel)
|
ciphertext, err := rsa.EncryptOAEP(hashfunc, rand.Reader, pubKey, plaintext, OAEPLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", errors.Wrapf(err, "rss.EncryptOAEP failed")
|
return nil, "", fmt.Errorf("rss.EncryptOAEP failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ciphertext, hashalg, nil
|
return ciphertext, hashalg, nil
|
||||||
|
@ -104,7 +105,7 @@ func pkcs11UriGetLoginParameters(p11uri *pkcs11uri.Pkcs11URI, privateKeyOperatio
|
||||||
|
|
||||||
module, err := p11uri.GetModule()
|
module, err := p11uri.GetModule()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", 0, errors.Wrap(err, "No module available in pkcs11 URI")
|
return "", "", 0, fmt.Errorf("No module available in pkcs11 URI: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
slotid := int64(-1)
|
slotid := int64(-1)
|
||||||
|
@ -113,7 +114,7 @@ func pkcs11UriGetLoginParameters(p11uri *pkcs11uri.Pkcs11URI, privateKeyOperatio
|
||||||
if ok {
|
if ok {
|
||||||
slotid, err = strconv.ParseInt(slot, 10, 64)
|
slotid, err = strconv.ParseInt(slot, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", 0, errors.Wrap(err, "slot-id is not a valid number")
|
return "", "", 0, fmt.Errorf("slot-id is not a valid number: %w", err)
|
||||||
}
|
}
|
||||||
if slotid < 0 {
|
if slotid < 0 {
|
||||||
return "", "", 0, fmt.Errorf("slot-id is a negative number")
|
return "", "", 0, fmt.Errorf("slot-id is a negative number")
|
||||||
|
@ -138,21 +139,21 @@ func pkcs11UriGetKeyIdAndLabel(p11uri *pkcs11uri.Pkcs11URI) (string, string, err
|
||||||
|
|
||||||
// pkcs11OpenSession opens a session with a pkcs11 device at the given slot and logs in with the given PIN
|
// pkcs11OpenSession opens a session with a pkcs11 device at the given slot and logs in with the given PIN
|
||||||
func pkcs11OpenSession(p11ctx *pkcs11.Ctx, slotid uint, pin string) (session pkcs11.SessionHandle, err error) {
|
func pkcs11OpenSession(p11ctx *pkcs11.Ctx, slotid uint, pin string) (session pkcs11.SessionHandle, err error) {
|
||||||
session, err = p11ctx.OpenSession(uint(slotid), pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
|
session, err = p11ctx.OpenSession(slotid, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrapf(err, "OpenSession to slot %d failed", slotid)
|
return 0, fmt.Errorf("OpenSession to slot %d failed: %w", slotid, err)
|
||||||
}
|
}
|
||||||
if len(pin) > 0 {
|
if len(pin) > 0 {
|
||||||
err = p11ctx.Login(session, pkcs11.CKU_USER, pin)
|
err = p11ctx.Login(session, pkcs11.CKU_USER, pin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = p11ctx.CloseSession(session)
|
_ = p11ctx.CloseSession(session)
|
||||||
return 0, errors.Wrap(err, "Could not login to device")
|
return 0, fmt.Errorf("Could not login to device: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return session, nil
|
return session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// pkcs11UriLogin uses the given pkcs11 URI to select the pkcs11 module (share libary) and to get
|
// pkcs11UriLogin uses the given pkcs11 URI to select the pkcs11 module (shared library) and to get
|
||||||
// the PIN to use for login; if the URI contains a slot-id, the given slot-id will be used, otherwise
|
// the PIN to use for login; if the URI contains a slot-id, the given slot-id will be used, otherwise
|
||||||
// one slot after the other will be attempted and the first one where login succeeds will be used
|
// one slot after the other will be attempted and the first one where login succeeds will be used
|
||||||
func pkcs11UriLogin(p11uri *pkcs11uri.Pkcs11URI, privateKeyOperation bool) (ctx *pkcs11.Ctx, session pkcs11.SessionHandle, err error) {
|
func pkcs11UriLogin(p11uri *pkcs11uri.Pkcs11URI, privateKeyOperation bool) (ctx *pkcs11.Ctx, session pkcs11.SessionHandle, err error) {
|
||||||
|
@ -170,40 +171,40 @@ func pkcs11UriLogin(p11uri *pkcs11uri.Pkcs11URI, privateKeyOperation bool) (ctx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p11Err := err.(pkcs11.Error)
|
p11Err := err.(pkcs11.Error)
|
||||||
if p11Err != pkcs11.CKR_CRYPTOKI_ALREADY_INITIALIZED {
|
if p11Err != pkcs11.CKR_CRYPTOKI_ALREADY_INITIALIZED {
|
||||||
return nil, 0, errors.Wrap(err, "Initialize failed")
|
return nil, 0, fmt.Errorf("Initialize failed: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if slotid >= 0 {
|
if slotid >= 0 {
|
||||||
session, err := pkcs11OpenSession(p11ctx, uint(slotid), pin)
|
session, err := pkcs11OpenSession(p11ctx, uint(slotid), pin)
|
||||||
return p11ctx, session, err
|
return p11ctx, session, err
|
||||||
} else {
|
|
||||||
slots, err := p11ctx.GetSlotList(true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, errors.Wrap(err, "GetSlotList failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenlabel, ok := p11uri.GetPathAttribute("token", false)
|
|
||||||
if !ok {
|
|
||||||
return nil, 0, errors.New("Missing 'token' attribute since 'slot-id' was not given")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, slot := range slots {
|
|
||||||
ti, err := p11ctx.GetTokenInfo(slot)
|
|
||||||
if err != nil || ti.Label != tokenlabel {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
session, err = pkcs11OpenSession(p11ctx, slot, pin)
|
|
||||||
if err == nil {
|
|
||||||
return p11ctx, session, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(pin) > 0 {
|
|
||||||
return nil, 0, errors.New("Could not create session to any slot and/or log in")
|
|
||||||
}
|
|
||||||
return nil, 0, errors.New("Could not create session to any slot")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slots, err := p11ctx.GetSlotList(true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, fmt.Errorf("GetSlotList failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenlabel, ok := p11uri.GetPathAttribute("token", false)
|
||||||
|
if !ok {
|
||||||
|
return nil, 0, errors.New("Missing 'token' attribute since 'slot-id' was not given")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, slot := range slots {
|
||||||
|
ti, err := p11ctx.GetTokenInfo(slot)
|
||||||
|
if err != nil || ti.Label != tokenlabel {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
session, err = pkcs11OpenSession(p11ctx, slot, pin)
|
||||||
|
if err == nil {
|
||||||
|
return p11ctx, session, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(pin) > 0 {
|
||||||
|
return nil, 0, errors.New("Could not create session to any slot and/or log in")
|
||||||
|
}
|
||||||
|
return nil, 0, errors.New("Could not create session to any slot")
|
||||||
}
|
}
|
||||||
|
|
||||||
func pkcs11Logout(ctx *pkcs11.Ctx, session pkcs11.SessionHandle) {
|
func pkcs11Logout(ctx *pkcs11.Ctx, session pkcs11.SessionHandle) {
|
||||||
|
@ -233,24 +234,24 @@ func findObject(p11ctx *pkcs11.Ctx, session pkcs11.SessionHandle, class uint, ke
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := p11ctx.FindObjectsInit(session, template); err != nil {
|
if err := p11ctx.FindObjectsInit(session, template); err != nil {
|
||||||
return 0, errors.Wrap(err, "FindObjectsInit failed")
|
return 0, fmt.Errorf("FindObjectsInit failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
obj, _, err := p11ctx.FindObjects(session, 100)
|
obj, _, err := p11ctx.FindObjects(session, 100)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "FindObjects failed")
|
return 0, fmt.Errorf("FindObjects failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := p11ctx.FindObjectsFinal(session); err != nil {
|
if err := p11ctx.FindObjectsFinal(session); err != nil {
|
||||||
return 0, errors.Wrap(err, "FindObjectsFinal failed")
|
return 0, fmt.Errorf("FindObjectsFinal failed: %w", err)
|
||||||
}
|
}
|
||||||
if len(obj) > 1 {
|
if len(obj) > 1 {
|
||||||
return 0, errors.Errorf("There are too many (=%d) keys with %s", len(obj), msg)
|
return 0, fmt.Errorf("There are too many (=%d) keys with %s", len(obj), msg)
|
||||||
} else if len(obj) == 1 {
|
} else if len(obj) == 1 {
|
||||||
return obj[0], nil
|
return obj[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, errors.Errorf("Could not find any object with %s", msg)
|
return 0, fmt.Errorf("Could not find any object with %s", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// publicEncryptOAEP uses a public key described by a pkcs11 URI to OAEP encrypt the given plaintext
|
// publicEncryptOAEP uses a public key described by a pkcs11 URI to OAEP encrypt the given plaintext
|
||||||
|
@ -290,17 +291,17 @@ func publicEncryptOAEP(pubKey *Pkcs11KeyFileObject, plaintext []byte) ([]byte, s
|
||||||
oaep = OAEPSha256Params
|
oaep = OAEPSha256Params
|
||||||
hashalg = "sha256"
|
hashalg = "sha256"
|
||||||
default:
|
default:
|
||||||
return nil, "", errors.Errorf("Unsupported OAEP hash '%s'", oaephash)
|
return nil, "", fmt.Errorf("Unsupported OAEP hash '%s'", oaephash)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = p11ctx.EncryptInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_OAEP, oaep)}, p11PubKey)
|
err = p11ctx.EncryptInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_OAEP, oaep)}, p11PubKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", errors.Wrap(err, "EncryptInit error")
|
return nil, "", fmt.Errorf("EncryptInit error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ciphertext, err := p11ctx.Encrypt(session, plaintext)
|
ciphertext, err := p11ctx.Encrypt(session, plaintext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", errors.Wrap(err, "Encrypt failed")
|
return nil, "", fmt.Errorf("Encrypt failed: %w", err)
|
||||||
}
|
}
|
||||||
return ciphertext, hashalg, nil
|
return ciphertext, hashalg, nil
|
||||||
}
|
}
|
||||||
|
@ -338,16 +339,16 @@ func privateDecryptOAEP(privKeyObj *Pkcs11KeyFileObject, ciphertext []byte, hash
|
||||||
case "sha256":
|
case "sha256":
|
||||||
oaep = OAEPSha256Params
|
oaep = OAEPSha256Params
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("Unsupported hash algorithm '%s' for decryption", hashalg)
|
return nil, fmt.Errorf("Unsupported hash algorithm '%s' for decryption", hashalg)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = p11ctx.DecryptInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_OAEP, oaep)}, p11PrivKey)
|
err = p11ctx.DecryptInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_OAEP, oaep)}, p11PrivKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "DecryptInit failed")
|
return nil, fmt.Errorf("DecryptInit failed: %w", err)
|
||||||
}
|
}
|
||||||
plaintext, err := p11ctx.Decrypt(session, ciphertext)
|
plaintext, err := p11ctx.Decrypt(session, ciphertext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "Decrypt failed")
|
return nil, fmt.Errorf("Decrypt failed: %w", err)
|
||||||
}
|
}
|
||||||
return plaintext, err
|
return plaintext, err
|
||||||
}
|
}
|
||||||
|
@ -373,19 +374,19 @@ type Pkcs11Recipient struct {
|
||||||
// may either be *rsa.PublicKey or *pkcs11uri.Pkcs11URI; the returned byte array is a JSON string of the
|
// may either be *rsa.PublicKey or *pkcs11uri.Pkcs11URI; the returned byte array is a JSON string of the
|
||||||
// following format:
|
// following format:
|
||||||
// {
|
// {
|
||||||
// recipients: [ // recipient list
|
// recipients: [ // recipient list
|
||||||
// {
|
// {
|
||||||
// "version": 0,
|
// "version": 0,
|
||||||
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
||||||
// "hash": <hash used for OAEP other than 'sha256'>
|
// "hash": <hash used for OAEP other than 'sha256'>
|
||||||
// } ,
|
// } ,
|
||||||
// {
|
// {
|
||||||
// "version": 0,
|
// "version": 0,
|
||||||
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
||||||
// "hash": <hash used for OAEP other than 'sha256'>
|
// "hash": <hash used for OAEP other than 'sha256'>
|
||||||
// } ,
|
// } ,
|
||||||
// [...]
|
// [...]
|
||||||
// ]
|
// ]
|
||||||
// }
|
// }
|
||||||
func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
|
func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
|
||||||
var (
|
var (
|
||||||
|
@ -402,7 +403,7 @@ func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
|
||||||
case *Pkcs11KeyFileObject:
|
case *Pkcs11KeyFileObject:
|
||||||
ciphertext, hashalg, err = publicEncryptOAEP(pkey, data)
|
ciphertext, hashalg, err = publicEncryptOAEP(pkey, data)
|
||||||
default:
|
default:
|
||||||
err = errors.Errorf("Unsupported key object type for pkcs11 public key")
|
err = fmt.Errorf("Unsupported key object type for pkcs11 public key")
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -422,33 +423,32 @@ func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
|
||||||
// Decrypt tries to decrypt one of the recipients' blobs using a pkcs11 private key.
|
// Decrypt tries to decrypt one of the recipients' blobs using a pkcs11 private key.
|
||||||
// The input pkcs11blobstr is a string with the following format:
|
// The input pkcs11blobstr is a string with the following format:
|
||||||
// {
|
// {
|
||||||
// recipients: [ // recipient list
|
// recipients: [ // recipient list
|
||||||
// {
|
// {
|
||||||
// "version": 0,
|
// "version": 0,
|
||||||
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
||||||
// "hash": <hash used for OAEP other than 'sha1'>
|
// "hash": <hash used for OAEP other than 'sha1'>
|
||||||
// } ,
|
// } ,
|
||||||
// {
|
// {
|
||||||
// "version": 0,
|
// "version": 0,
|
||||||
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
// "blob": <base64 encoded RSA OAEP encrypted blob>,
|
||||||
// "hash": <hash used for OAEP other than 'sha1'>
|
// "hash": <hash used for OAEP other than 'sha1'>
|
||||||
// } ,
|
// } ,
|
||||||
// [...]
|
// [...]
|
||||||
// }
|
// }
|
||||||
// Note: More recent versions of this code explicitly write 'sha1'
|
// Note: More recent versions of this code explicitly write 'sha1'
|
||||||
// while older versions left it empty in case of 'sha1'.
|
// while older versions left it empty in case of 'sha1'.
|
||||||
//
|
|
||||||
func Decrypt(privKeyObjs []*Pkcs11KeyFileObject, pkcs11blobstr []byte) ([]byte, error) {
|
func Decrypt(privKeyObjs []*Pkcs11KeyFileObject, pkcs11blobstr []byte) ([]byte, error) {
|
||||||
pkcs11blob := Pkcs11Blob{}
|
pkcs11blob := Pkcs11Blob{}
|
||||||
err := json.Unmarshal(pkcs11blobstr, &pkcs11blob)
|
err := json.Unmarshal(pkcs11blobstr, &pkcs11blob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "Could not parse Pkcs11Blob")
|
return nil, fmt.Errorf("Could not parse Pkcs11Blob: %w", err)
|
||||||
}
|
}
|
||||||
switch pkcs11blob.Version {
|
switch pkcs11blob.Version {
|
||||||
case 0:
|
case 0:
|
||||||
// latest supported version
|
// latest supported version
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("Found Pkcs11Blob with version %d but maximum supported version is 0.", pkcs11blob.Version)
|
return nil, fmt.Errorf("found Pkcs11Blob with version %d but maximum supported version is 0", pkcs11blob.Version)
|
||||||
}
|
}
|
||||||
// since we do trial and error, collect all encountered errors
|
// since we do trial and error, collect all encountered errors
|
||||||
errs := ""
|
errs := ""
|
||||||
|
@ -458,7 +458,7 @@ func Decrypt(privKeyObjs []*Pkcs11KeyFileObject, pkcs11blobstr []byte) ([]byte,
|
||||||
case 0:
|
case 0:
|
||||||
// last supported version
|
// last supported version
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("Found Pkcs11Recipient with version %d but maximum supported version is 0.", recipient.Version)
|
return nil, fmt.Errorf("found Pkcs11Recipient with version %d but maximum supported version is 0", recipient.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
ciphertext, err := base64.StdEncoding.DecodeString(recipient.Blob)
|
ciphertext, err := base64.StdEncoding.DecodeString(recipient.Blob)
|
||||||
|
@ -481,5 +481,5 @@ func Decrypt(privKeyObjs []*Pkcs11KeyFileObject, pkcs11blobstr []byte) ([]byte,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.Errorf("Could not find a pkcs11 key for decryption:\n%s", errs)
|
return nil, fmt.Errorf("Could not find a pkcs11 key for decryption:\n%s", errs)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !cgo
|
||||||
// +build !cgo
|
// +build !cgo
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -18,14 +19,12 @@
|
||||||
|
|
||||||
package pkcs11
|
package pkcs11
|
||||||
|
|
||||||
import (
|
import "fmt"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
|
func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
|
||||||
return nil, errors.Errorf("ocicrypt pkcs11 not supported on this build")
|
return nil, fmt.Errorf("ocicrypt pkcs11 not supported on this build")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Decrypt(privKeyObjs []*Pkcs11KeyFileObject, pkcs11blobstr []byte) ([]byte, error) {
|
func Decrypt(privKeyObjs []*Pkcs11KeyFileObject, pkcs11blobstr []byte) ([]byte, error) {
|
||||||
return nil, errors.Errorf("ocicrypt pkcs11 not supported on this build")
|
return nil, fmt.Errorf("ocicrypt pkcs11 not supported on this build")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build cgo
|
||||||
// +build cgo
|
// +build cgo
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -17,12 +17,11 @@
|
||||||
package pkcs11
|
package pkcs11
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -45,7 +44,7 @@ func setEnvVars(env map[string]string) ([]string, error) {
|
||||||
err := os.Setenv(k, v)
|
err := os.Setenv(k, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
restoreEnv(oldenv)
|
restoreEnv(oldenv)
|
||||||
return nil, errors.Wrapf(err, "Could not set environment variable '%s' to '%s'", k, v)
|
return nil, fmt.Errorf("Could not set environment variable '%s' to '%s': %w", k, v, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +105,8 @@ func getHostAndOsType() (string, string, string) {
|
||||||
ht = "x86_64"
|
ht = "x86_64"
|
||||||
case "ppc64le":
|
case "ppc64le":
|
||||||
ht = "powerpc64le"
|
ht = "powerpc64le"
|
||||||
|
case "riscv64":
|
||||||
|
ht = "riscv64"
|
||||||
case "s390x":
|
case "s390x":
|
||||||
ht = "s390x"
|
ht = "s390x"
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,23 +19,23 @@ package ocicrypt
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
keyproviderconfig "github.com/containers/ocicrypt/config/keyprovider-config"
|
|
||||||
"github.com/containers/ocicrypt/keywrap/keyprovider"
|
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containers/ocicrypt/blockcipher"
|
"github.com/containers/ocicrypt/blockcipher"
|
||||||
"github.com/containers/ocicrypt/config"
|
"github.com/containers/ocicrypt/config"
|
||||||
|
keyproviderconfig "github.com/containers/ocicrypt/config/keyprovider-config"
|
||||||
"github.com/containers/ocicrypt/keywrap"
|
"github.com/containers/ocicrypt/keywrap"
|
||||||
"github.com/containers/ocicrypt/keywrap/jwe"
|
"github.com/containers/ocicrypt/keywrap/jwe"
|
||||||
|
"github.com/containers/ocicrypt/keywrap/keyprovider"
|
||||||
"github.com/containers/ocicrypt/keywrap/pgp"
|
"github.com/containers/ocicrypt/keywrap/pgp"
|
||||||
"github.com/containers/ocicrypt/keywrap/pkcs11"
|
"github.com/containers/ocicrypt/keywrap/pkcs11"
|
||||||
"github.com/containers/ocicrypt/keywrap/pkcs7"
|
"github.com/containers/ocicrypt/keywrap/pkcs7"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EncryptLayerFinalizer is a finalizer run to return the annotations to set for
|
// EncryptLayerFinalizer is a finalizer run to return the annotations to set for
|
||||||
|
@ -133,16 +133,19 @@ func EncryptLayer(ec *config.EncryptConfig, encOrPlainLayerReader io.Reader, des
|
||||||
}
|
}
|
||||||
privOptsData, err = json.Marshal(opts.Private)
|
privOptsData, err = json.Marshal(opts.Private)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not JSON marshal opts")
|
return nil, fmt.Errorf("could not JSON marshal opts: %w", err)
|
||||||
}
|
}
|
||||||
pubOptsData, err = json.Marshal(opts.Public)
|
pubOptsData, err = json.Marshal(opts.Public)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not JSON marshal opts")
|
return nil, fmt.Errorf("could not JSON marshal opts: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newAnnotations := make(map[string]string)
|
newAnnotations := make(map[string]string)
|
||||||
keysWrapped := false
|
keysWrapped := false
|
||||||
|
if len(keyWrapperAnnotations) == 0 {
|
||||||
|
return nil, errors.New("missing Annotations needed for decryption")
|
||||||
|
}
|
||||||
for annotationsID, scheme := range keyWrapperAnnotations {
|
for annotationsID, scheme := range keyWrapperAnnotations {
|
||||||
b64Annotations := desc.Annotations[annotationsID]
|
b64Annotations := desc.Annotations[annotationsID]
|
||||||
keywrapper := GetKeyWrapper(scheme)
|
keywrapper := GetKeyWrapper(scheme)
|
||||||
|
@ -211,6 +214,9 @@ func DecryptLayer(dc *config.DecryptConfig, encLayerReader io.Reader, desc ocisp
|
||||||
func decryptLayerKeyOptsData(dc *config.DecryptConfig, desc ocispec.Descriptor) ([]byte, error) {
|
func decryptLayerKeyOptsData(dc *config.DecryptConfig, desc ocispec.Descriptor) ([]byte, error) {
|
||||||
privKeyGiven := false
|
privKeyGiven := false
|
||||||
errs := ""
|
errs := ""
|
||||||
|
if len(keyWrapperAnnotations) == 0 {
|
||||||
|
return nil, errors.New("missing Annotations needed for decryption")
|
||||||
|
}
|
||||||
for annotationsID, scheme := range keyWrapperAnnotations {
|
for annotationsID, scheme := range keyWrapperAnnotations {
|
||||||
b64Annotation := desc.Annotations[annotationsID]
|
b64Annotation := desc.Annotations[annotationsID]
|
||||||
if b64Annotation != "" {
|
if b64Annotation != "" {
|
||||||
|
@ -237,9 +243,9 @@ func decryptLayerKeyOptsData(dc *config.DecryptConfig, desc ocispec.Descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !privKeyGiven {
|
if !privKeyGiven {
|
||||||
return nil, errors.New("missing private key needed for decryption")
|
return nil, fmt.Errorf("missing private key needed for decryption:\n%s", errs)
|
||||||
}
|
}
|
||||||
return nil, errors.Errorf("no suitable key unwrapper found or none of the private keys could be used for decryption:\n%s", errs)
|
return nil, fmt.Errorf("no suitable key unwrapper found or none of the private keys could be used for decryption:\n%s", errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLayerPubOpts(desc ocispec.Descriptor) ([]byte, error) {
|
func getLayerPubOpts(desc ocispec.Descriptor) ([]byte, error) {
|
||||||
|
@ -270,7 +276,7 @@ func preUnwrapKey(keywrapper keywrap.KeyWrapper, dc *config.DecryptConfig, b64An
|
||||||
}
|
}
|
||||||
return optsData, nil
|
return optsData, nil
|
||||||
}
|
}
|
||||||
return nil, errors.Errorf("no suitable key found for decrypting layer key:\n%s", errs)
|
return nil, fmt.Errorf("no suitable key found for decrypting layer key:\n%s", errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// commonEncryptLayer is a function to encrypt the plain layer using a new random
|
// commonEncryptLayer is a function to encrypt the plain layer using a new random
|
||||||
|
@ -305,7 +311,7 @@ func commonDecryptLayer(encLayerReader io.Reader, privOptsData []byte, pubOptsDa
|
||||||
privOpts := blockcipher.PrivateLayerBlockCipherOptions{}
|
privOpts := blockcipher.PrivateLayerBlockCipherOptions{}
|
||||||
err := json.Unmarshal(privOptsData, &privOpts)
|
err := json.Unmarshal(privOptsData, &privOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", errors.Wrapf(err, "could not JSON unmarshal privOptsData")
|
return nil, "", fmt.Errorf("could not JSON unmarshal privOptsData: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lbch, err := blockcipher.NewLayerBlockCipherHandler()
|
lbch, err := blockcipher.NewLayerBlockCipherHandler()
|
||||||
|
@ -317,7 +323,7 @@ func commonDecryptLayer(encLayerReader io.Reader, privOptsData []byte, pubOptsDa
|
||||||
if len(pubOptsData) > 0 {
|
if len(pubOptsData) > 0 {
|
||||||
err := json.Unmarshal(pubOptsData, &pubOpts)
|
err := json.Unmarshal(pubOptsData, &pubOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", errors.Wrapf(err, "could not JSON unmarshal pubOptsData")
|
return nil, "", fmt.Errorf("could not JSON unmarshal pubOptsData: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
go.mod
35
go.mod
|
@ -1,21 +1,30 @@
|
||||||
module github.com/containers/ocicrypt
|
module github.com/containers/ocicrypt
|
||||||
|
|
||||||
go 1.12
|
go 1.22
|
||||||
|
toolchain go1.24.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang/protobuf v1.4.3
|
github.com/go-jose/go-jose/v4 v4.0.5
|
||||||
github.com/google/go-cmp v0.5.2 // indirect
|
github.com/golang/protobuf v1.5.4
|
||||||
github.com/miekg/pkcs11 v1.1.1
|
github.com/miekg/pkcs11 v1.1.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
|
github.com/opencontainers/image-spec v1.1.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/sirupsen/logrus v1.7.0
|
github.com/smallstep/pkcs7 v0.1.1
|
||||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980
|
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.10.0
|
||||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1
|
golang.org/x/crypto v0.36.0
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
golang.org/x/term v0.30.0
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1
|
google.golang.org/grpc v1.68.1
|
||||||
google.golang.org/grpc v1.33.2
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1
|
)
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
golang.org/x/net v0.38.0 // indirect
|
||||||
|
golang.org/x/sys v0.31.0 // indirect
|
||||||
|
golang.org/x/text v0.23.0 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||||
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
)
|
)
|
||||||
|
|
183
go.sum
183
go.sum
|
@ -1,117 +1,112 @@
|
||||||
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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
|
||||||
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
|
||||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
||||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU=
|
||||||
|
github.com/smallstep/pkcs7 v0.1.1/go.mod h1:dL6j5AIz9GHjVEBTXtW+QliALcgM19RtXaTeyxI+AfA=
|
||||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I=
|
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I=
|
||||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
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-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
|
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||||
|
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
|
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
|
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
|
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||||
|
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||||
|
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||||
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.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
|
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|
||||||
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=
|
|
||||||
|
|
26
gpg.go
26
gpg.go
|
@ -17,16 +17,17 @@
|
||||||
package ocicrypt
|
package ocicrypt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -78,9 +79,8 @@ func GuessGPGVersion() GPGVersion {
|
||||||
return GPGv2
|
return GPGv2
|
||||||
} else if err := exec.Command("gpg", "--version").Run(); err == nil {
|
} else if err := exec.Command("gpg", "--version").Run(); err == nil {
|
||||||
return GPGv1
|
return GPGv1
|
||||||
} else {
|
|
||||||
return GPGVersionUndetermined
|
|
||||||
}
|
}
|
||||||
|
return GPGVersionUndetermined
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGPGClient creates a new GPGClient object representing the given version
|
// NewGPGClient creates a new GPGClient object representing the given version
|
||||||
|
@ -132,7 +132,7 @@ func (gc *gpgv2Client) GetGPGPrivateKey(keyid uint64, passphrase string) ([]byte
|
||||||
|
|
||||||
rfile, wfile, err := os.Pipe()
|
rfile, wfile, err := os.Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not create pipe")
|
return nil, fmt.Errorf("could not create pipe: %w", err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
rfile.Close()
|
rfile.Close()
|
||||||
|
@ -272,8 +272,8 @@ func runGPGGetOutput(cmd *exec.Cmd) ([]byte, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
stdoutstr, err2 := ioutil.ReadAll(stdout)
|
stdoutstr, err2 := io.ReadAll(stdout)
|
||||||
stderrstr, _ := ioutil.ReadAll(stderr)
|
stderrstr, _ := io.ReadAll(stderr)
|
||||||
|
|
||||||
if err := cmd.Wait(); err != nil {
|
if err := cmd.Wait(); err != nil {
|
||||||
return nil, fmt.Errorf("error from %s: %s", cmd.Path, string(stderrstr))
|
return nil, fmt.Errorf("error from %s: %s", cmd.Path, string(stderrstr))
|
||||||
|
@ -310,9 +310,15 @@ func resolveRecipients(gc GPGClient, recipients []string) []string {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
var emailPattern = regexp.MustCompile(`uid\s+\[.*\]\s.*\s<(?P<email>.+)>`)
|
var (
|
||||||
|
onceRegexp sync.Once
|
||||||
|
emailPattern *regexp.Regexp
|
||||||
|
)
|
||||||
|
|
||||||
func extractEmailFromDetails(details []byte) string {
|
func extractEmailFromDetails(details []byte) string {
|
||||||
|
onceRegexp.Do(func() {
|
||||||
|
emailPattern = regexp.MustCompile(`uid\s+\[.*\]\s.*\s<(?P<email>.+)>`)
|
||||||
|
})
|
||||||
loc := emailPattern.FindSubmatchIndex(details)
|
loc := emailPattern.FindSubmatchIndex(details)
|
||||||
if len(loc) == 0 {
|
if len(loc) == 0 {
|
||||||
return ""
|
return ""
|
||||||
|
@ -352,7 +358,7 @@ func GPGGetPrivateKey(descs []ocispec.Descriptor, gpgClient GPGClient, gpgVault
|
||||||
}
|
}
|
||||||
keywrapper := GetKeyWrapper(scheme)
|
keywrapper := GetKeyWrapper(scheme)
|
||||||
if keywrapper == nil {
|
if keywrapper == nil {
|
||||||
return nil, nil, errors.Errorf("could not get KeyWrapper for %s\n", scheme)
|
return nil, nil, fmt.Errorf("could not get KeyWrapper for %s", scheme)
|
||||||
}
|
}
|
||||||
keyIds, err := keywrapper.GetKeyIdsFromPacket(b64pgpPackets)
|
keyIds, err := keywrapper.GetKeyIdsFromPacket(b64pgpPackets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -411,7 +417,7 @@ func GPGGetPrivateKey(descs []ocispec.Descriptor, gpgClient GPGClient, gpgVault
|
||||||
if !found && len(b64pgpPackets) > 0 && mustFindKey {
|
if !found && len(b64pgpPackets) > 0 && mustFindKey {
|
||||||
ids := uint64ToStringArray("0x%x", keyIds)
|
ids := uint64ToStringArray("0x%x", keyIds)
|
||||||
|
|
||||||
return nil, nil, errors.Errorf("missing key for decryption of layer %x of %s. Need one of the following keys: %s", desc.Digest, desc.Platform, strings.Join(ids, ", "))
|
return nil, nil, fmt.Errorf("missing key for decryption of layer %x of %s. Need one of the following keys: %s", desc.Digest, desc.Platform, strings.Join(ids, ", "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ package ocicrypt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/crypto/openpgp"
|
"golang.org/x/crypto/openpgp"
|
||||||
"golang.org/x/crypto/openpgp/packet"
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
)
|
)
|
||||||
|
@ -55,7 +55,7 @@ func (g *gpgVault) AddSecretKeyRingData(gpgSecretKeyRingData []byte) error {
|
||||||
r := bytes.NewReader(gpgSecretKeyRingData)
|
r := bytes.NewReader(gpgSecretKeyRingData)
|
||||||
entityList, err := openpgp.ReadKeyRing(r)
|
entityList, err := openpgp.ReadKeyRing(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "could not read keyring")
|
return fmt.Errorf("could not read keyring: %w", err)
|
||||||
}
|
}
|
||||||
g.entityLists = append(g.entityLists, entityList)
|
g.entityLists = append(g.entityLists, entityList)
|
||||||
g.keyDataList = append(g.keyDataList, gpgSecretKeyRingData)
|
g.keyDataList = append(g.keyDataList, gpgSecretKeyRingData)
|
||||||
|
@ -76,7 +76,7 @@ func (g *gpgVault) AddSecretKeyRingDataArray(gpgSecretKeyRingDataArray [][]byte)
|
||||||
// AddSecretKeyRingFiles adds the secret key rings given their filenames
|
// AddSecretKeyRingFiles adds the secret key rings given their filenames
|
||||||
func (g *gpgVault) AddSecretKeyRingFiles(filenames []string) error {
|
func (g *gpgVault) AddSecretKeyRingFiles(filenames []string) error {
|
||||||
for _, filename := range filenames {
|
for _, filename := range filenames {
|
||||||
gpgSecretKeyRingData, err := ioutil.ReadFile(filename)
|
gpgSecretKeyRingData, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -12,8 +12,6 @@ import (
|
||||||
"github.com/containers/ocicrypt/config/pkcs11config"
|
"github.com/containers/ocicrypt/config/pkcs11config"
|
||||||
"github.com/containers/ocicrypt/crypto/pkcs11"
|
"github.com/containers/ocicrypt/crypto/pkcs11"
|
||||||
encutils "github.com/containers/ocicrypt/utils"
|
encutils "github.com/containers/ocicrypt/utils"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// processRecipientKeys sorts the array of recipients by type. Recipients may be either
|
// processRecipientKeys sorts the array of recipients by type. Recipients may be either
|
||||||
|
@ -43,9 +41,9 @@ func processRecipientKeys(recipients []string) ([][]byte, [][]byte, [][]byte, []
|
||||||
gpgRecipients = append(gpgRecipients, []byte(value))
|
gpgRecipients = append(gpgRecipients, []byte(value))
|
||||||
|
|
||||||
case "jwe":
|
case "jwe":
|
||||||
tmp, err := ioutil.ReadFile(value)
|
tmp, err := os.ReadFile(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, nil, nil, errors.Wrap(err, "Unable to read file")
|
return nil, nil, nil, nil, nil, nil, fmt.Errorf("Unable to read file: %w", err)
|
||||||
}
|
}
|
||||||
if !encutils.IsPublicKey(tmp) {
|
if !encutils.IsPublicKey(tmp) {
|
||||||
return nil, nil, nil, nil, nil, nil, errors.New("File provided is not a public key")
|
return nil, nil, nil, nil, nil, nil, errors.New("File provided is not a public key")
|
||||||
|
@ -53,9 +51,9 @@ func processRecipientKeys(recipients []string) ([][]byte, [][]byte, [][]byte, []
|
||||||
pubkeys = append(pubkeys, tmp)
|
pubkeys = append(pubkeys, tmp)
|
||||||
|
|
||||||
case "pkcs7":
|
case "pkcs7":
|
||||||
tmp, err := ioutil.ReadFile(value)
|
tmp, err := os.ReadFile(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, nil, nil, errors.Wrap(err, "Unable to read file")
|
return nil, nil, nil, nil, nil, nil, fmt.Errorf("Unable to read file: %w", err)
|
||||||
}
|
}
|
||||||
if !encutils.IsCertificate(tmp) {
|
if !encutils.IsCertificate(tmp) {
|
||||||
return nil, nil, nil, nil, nil, nil, errors.New("File provided is not an x509 cert")
|
return nil, nil, nil, nil, nil, nil, errors.New("File provided is not an x509 cert")
|
||||||
|
@ -63,9 +61,9 @@ func processRecipientKeys(recipients []string) ([][]byte, [][]byte, [][]byte, []
|
||||||
x509s = append(x509s, tmp)
|
x509s = append(x509s, tmp)
|
||||||
|
|
||||||
case "pkcs11":
|
case "pkcs11":
|
||||||
tmp, err := ioutil.ReadFile(value)
|
tmp, err := os.ReadFile(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, nil, nil, errors.Wrap(err, "Unable to read file")
|
return nil, nil, nil, nil, nil, nil, fmt.Errorf("Unable to read file: %w", err)
|
||||||
}
|
}
|
||||||
if encutils.IsPkcs11PublicKey(tmp) {
|
if encutils.IsPkcs11PublicKey(tmp) {
|
||||||
pkcs11Yamls = append(pkcs11Yamls, tmp)
|
pkcs11Yamls = append(pkcs11Yamls, tmp)
|
||||||
|
@ -93,9 +91,9 @@ func processx509Certs(keys []string) ([][]byte, error) {
|
||||||
if _, err := os.Stat(fileName); os.IsNotExist(err) {
|
if _, err := os.Stat(fileName); os.IsNotExist(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tmp, err := ioutil.ReadFile(fileName)
|
tmp, err := os.ReadFile(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Unable to read file")
|
return nil, fmt.Errorf("Unable to read file: %w", err)
|
||||||
}
|
}
|
||||||
if !encutils.IsCertificate(tmp) {
|
if !encutils.IsCertificate(tmp) {
|
||||||
continue
|
continue
|
||||||
|
@ -113,14 +111,14 @@ func processx509Certs(keys []string) ([][]byte, error) {
|
||||||
// - <password>
|
// - <password>
|
||||||
func processPwdString(pwdString string) ([]byte, error) {
|
func processPwdString(pwdString string) ([]byte, error) {
|
||||||
if strings.HasPrefix(pwdString, "file=") {
|
if strings.HasPrefix(pwdString, "file=") {
|
||||||
return ioutil.ReadFile(pwdString[5:])
|
return os.ReadFile(pwdString[5:])
|
||||||
} else if strings.HasPrefix(pwdString, "pass=") {
|
} else if strings.HasPrefix(pwdString, "pass=") {
|
||||||
return []byte(pwdString[5:]), nil
|
return []byte(pwdString[5:]), nil
|
||||||
} else if strings.HasPrefix(pwdString, "fd=") {
|
} else if strings.HasPrefix(pwdString, "fd=") {
|
||||||
fdStr := pwdString[3:]
|
fdStr := pwdString[3:]
|
||||||
fd, err := strconv.Atoi(fdStr)
|
fd, err := strconv.Atoi(fdStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not parse file descriptor %s", fdStr)
|
return nil, fmt.Errorf("could not parse file descriptor %s: %w", fdStr, err)
|
||||||
}
|
}
|
||||||
f := os.NewFile(uintptr(fd), "pwdfile")
|
f := os.NewFile(uintptr(fd), "pwdfile")
|
||||||
if f == nil {
|
if f == nil {
|
||||||
|
@ -130,7 +128,7 @@ func processPwdString(pwdString string) ([]byte, error) {
|
||||||
pwd := make([]byte, 64)
|
pwd := make([]byte, 64)
|
||||||
n, err := f.Read(pwd)
|
n, err := f.Read(pwd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not read from file descriptor")
|
return nil, fmt.Errorf("could not read from file descriptor: %w", err)
|
||||||
}
|
}
|
||||||
return pwd[:n], nil
|
return pwd[:n], nil
|
||||||
}
|
}
|
||||||
|
@ -174,7 +172,7 @@ func processPrivateKeyFiles(keyFilesAndPwds []string) ([][]byte, [][]byte, [][]b
|
||||||
}
|
}
|
||||||
|
|
||||||
keyfile := parts[0]
|
keyfile := parts[0]
|
||||||
tmp, err := ioutil.ReadFile(keyfile)
|
tmp, err := os.ReadFile(keyfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -374,7 +372,6 @@ func CreateCryptoConfig(recipients []string, keys []string) (encconfig.CryptoCon
|
||||||
|
|
||||||
if len(ccs) > 0 {
|
if len(ccs) > 0 {
|
||||||
return encconfig.CombineCryptoConfigs(ccs), nil
|
return encconfig.CombineCryptoConfigs(ccs), nil
|
||||||
} else {
|
|
||||||
return encconfig.CryptoConfig{}, nil
|
|
||||||
}
|
}
|
||||||
|
return encconfig.CryptoConfig{}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,13 @@ package jwe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"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/pkg/errors"
|
"github.com/go-jose/go-jose/v4"
|
||||||
jose "gopkg.in/square/go-jose.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type jweKeyWrapper struct {
|
type jweKeyWrapper struct {
|
||||||
|
@ -54,17 +55,21 @@ func (kw *jweKeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]
|
||||||
|
|
||||||
encrypter, err := jose.NewMultiEncrypter(jose.A256GCM, joseRecipients, nil)
|
encrypter, err := jose.NewMultiEncrypter(jose.A256GCM, joseRecipients, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "jose.NewMultiEncrypter failed")
|
return nil, fmt.Errorf("jose.NewMultiEncrypter failed: %w", err)
|
||||||
}
|
}
|
||||||
jwe, err := encrypter.Encrypt(optsData)
|
jwe, err := encrypter.Encrypt(optsData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "JWE Encrypt failed")
|
return nil, fmt.Errorf("JWE Encrypt failed: %w", err)
|
||||||
}
|
}
|
||||||
return []byte(jwe.FullSerialize()), nil
|
return []byte(jwe.FullSerialize()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kw *jweKeyWrapper) UnwrapKey(dc *config.DecryptConfig, jweString []byte) ([]byte, error) {
|
func (kw *jweKeyWrapper) UnwrapKey(dc *config.DecryptConfig, jweString []byte) ([]byte, error) {
|
||||||
jwe, err := jose.ParseEncrypted(string(jweString))
|
// cf. list of algorithms in func addPubKeys() below
|
||||||
|
keyEncryptionAlgorithms := []jose.KeyAlgorithm{jose.RSA_OAEP, jose.RSA_OAEP_256, jose.ECDH_ES_A128KW, jose.ECDH_ES_A192KW, jose.ECDH_ES_A256KW}
|
||||||
|
// accept all algorithms defined in RFC 7518, section 5.1
|
||||||
|
contentEncryption := []jose.ContentEncryption{jose.A128CBC_HS256, jose.A192CBC_HS384, jose.A256CBC_HS512, jose.A128GCM, jose.A192GCM, jose.A256GCM}
|
||||||
|
jwe, err := jose.ParseEncrypted(string(jweString), keyEncryptionAlgorithms, contentEncryption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("jose.ParseEncrypted failed")
|
return nil, errors.New("jose.ParseEncrypted failed")
|
||||||
}
|
}
|
||||||
|
@ -122,9 +127,24 @@ func addPubKeys(joseRecipients *[]jose.Recipient, pubKeys [][]byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
alg := jose.RSA_OAEP
|
alg := jose.RSA_OAEP
|
||||||
switch key.(type) {
|
switch key := key.(type) {
|
||||||
case *ecdsa.PublicKey:
|
case *ecdsa.PublicKey:
|
||||||
alg = jose.ECDH_ES_A256KW
|
alg = jose.ECDH_ES_A256KW
|
||||||
|
case *jose.JSONWebKey:
|
||||||
|
if key.Algorithm != "" {
|
||||||
|
alg = jose.KeyAlgorithm(key.Algorithm)
|
||||||
|
switch alg {
|
||||||
|
/* accepted algorithms */
|
||||||
|
case jose.RSA_OAEP:
|
||||||
|
case jose.RSA_OAEP_256:
|
||||||
|
case jose.ECDH_ES_A128KW:
|
||||||
|
case jose.ECDH_ES_A192KW:
|
||||||
|
case jose.ECDH_ES_A256KW:
|
||||||
|
/* all others are rejected */
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("%s is an unsupported JWE key algorithm", alg)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*joseRecipients = append(*joseRecipients, jose.Recipient{
|
*joseRecipients = append(*joseRecipients, jose.Recipient{
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
"github.com/containers/ocicrypt/config"
|
"github.com/containers/ocicrypt/config"
|
||||||
"github.com/containers/ocicrypt/utils"
|
"github.com/containers/ocicrypt/utils"
|
||||||
jose "gopkg.in/square/go-jose.v2"
|
"github.com/go-jose/go-jose/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
var oneEmpty []byte
|
var oneEmpty []byte
|
||||||
|
@ -70,6 +70,21 @@ func createValidJweCcs() ([]*config.CryptoConfig, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ecKey, err := utils.CreateECDSAKey(elliptic.P521())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
jweEcPrivKeyJwk, err := jose.JSONWebKey{Key: ecKey, Algorithm: string(jose.ECDH_ES_A256KW)}.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
jweEcPubKeyJwk, err := jose.JSONWebKey{Key: &ecKey.PublicKey, Algorithm: string(jose.ECDH_ES_A256KW)}.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
validJweCcs := []*config.CryptoConfig{
|
validJweCcs := []*config.CryptoConfig{
|
||||||
// Key 1
|
// Key 1
|
||||||
{
|
{
|
||||||
|
@ -226,6 +241,27 @@ func createValidJweCcs() ([]*config.CryptoConfig, error) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// EC Key (JWK format)
|
||||||
|
{
|
||||||
|
EncryptConfig: &config.EncryptConfig{
|
||||||
|
Parameters: map[string][][]byte{
|
||||||
|
"pubkeys": {jweEcPubKeyJwk},
|
||||||
|
},
|
||||||
|
DecryptConfig: config.DecryptConfig{
|
||||||
|
Parameters: map[string][][]byte{
|
||||||
|
"privkeys": {jweEcPrivKeyJwk},
|
||||||
|
"privkeys-passwords": {oneEmpty},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
DecryptConfig: &config.DecryptConfig{
|
||||||
|
Parameters: map[string][][]byte{
|
||||||
|
"privkeys": {jweEcPrivKeyJwk},
|
||||||
|
"privkeys-passwords": {oneEmpty},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return validJweCcs, nil
|
return validJweCcs, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,14 @@ package keyprovider
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/containers/ocicrypt/config"
|
"github.com/containers/ocicrypt/config"
|
||||||
keyproviderconfig "github.com/containers/ocicrypt/config/keyprovider-config"
|
keyproviderconfig "github.com/containers/ocicrypt/config/keyprovider-config"
|
||||||
"github.com/containers/ocicrypt/keywrap"
|
"github.com/containers/ocicrypt/keywrap"
|
||||||
"github.com/containers/ocicrypt/utils"
|
"github.com/containers/ocicrypt/utils"
|
||||||
keyproviderpb "github.com/containers/ocicrypt/utils/keyprovider"
|
keyproviderpb "github.com/containers/ocicrypt/utils/keyprovider"
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
@ -112,19 +114,18 @@ func (kw *keyProviderKeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []b
|
||||||
if kw.attrs.Command != nil {
|
if kw.attrs.Command != nil {
|
||||||
protocolOuput, err := getProviderCommandOutput(input, kw.attrs.Command)
|
protocolOuput, err := getProviderCommandOutput(input, kw.attrs.Command)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error while retrieving keyprovider protocol command output")
|
return nil, fmt.Errorf("error while retrieving keyprovider protocol command output: %w", err)
|
||||||
}
|
}
|
||||||
return protocolOuput.KeyWrapResults.Annotation, nil
|
return protocolOuput.KeyWrapResults.Annotation, nil
|
||||||
} else if kw.attrs.Grpc != "" {
|
} else if kw.attrs.Grpc != "" {
|
||||||
protocolOuput, err := getProviderGRPCOutput(input, kw.attrs.Grpc, OpKeyWrap)
|
protocolOuput, err := getProviderGRPCOutput(input, kw.attrs.Grpc, OpKeyWrap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error while retrieving keyprovider protocol grpc output")
|
return nil, fmt.Errorf("error while retrieving keyprovider protocol grpc output: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return protocolOuput.KeyWrapResults.Annotation, nil
|
return protocolOuput.KeyWrapResults.Annotation, nil
|
||||||
} else {
|
|
||||||
return nil, errors.New("Unsupported keyprovider invocation. Supported invocation methods are grpc and cmd")
|
|
||||||
}
|
}
|
||||||
|
return nil, errors.New("Unsupported keyprovider invocation. Supported invocation methods are grpc and cmd")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -160,9 +161,8 @@ func (kw *keyProviderKeyWrapper) UnwrapKey(dc *config.DecryptConfig, jsonString
|
||||||
}
|
}
|
||||||
|
|
||||||
return protocolOuput.KeyUnwrapResults.OptsData, nil
|
return protocolOuput.KeyUnwrapResults.OptsData, nil
|
||||||
} else {
|
|
||||||
return nil, errors.New("Unsupported keyprovider invocation. Supported invocation methods are grpc and cmd")
|
|
||||||
}
|
}
|
||||||
|
return nil, errors.New("Unsupported keyprovider invocation. Supported invocation methods are grpc and cmd")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getProviderGRPCOutput(input []byte, connString string, operation KeyProviderKeyWrapProtocolOperation) (*KeyProviderKeyWrapProtocolOutput, error) {
|
func getProviderGRPCOutput(input []byte, connString string, operation KeyProviderKeyWrapProtocolOperation) (*KeyProviderKeyWrapProtocolOutput, error) {
|
||||||
|
@ -170,7 +170,7 @@ func getProviderGRPCOutput(input []byte, connString string, operation KeyProvide
|
||||||
var grpcOutput *keyproviderpb.KeyProviderKeyWrapProtocolOutput
|
var grpcOutput *keyproviderpb.KeyProviderKeyWrapProtocolOutput
|
||||||
cc, err := grpc.Dial(connString, grpc.WithInsecure())
|
cc, err := grpc.Dial(connString, grpc.WithInsecure())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error while dialing rpc server")
|
return nil, fmt.Errorf("error while dialing rpc server: %w", err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
derr := cc.Close()
|
derr := cc.Close()
|
||||||
|
@ -187,12 +187,12 @@ func getProviderGRPCOutput(input []byte, connString string, operation KeyProvide
|
||||||
if operation == OpKeyWrap {
|
if operation == OpKeyWrap {
|
||||||
grpcOutput, err = client.WrapKey(context.Background(), req)
|
grpcOutput, err = client.WrapKey(context.Background(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Error from grpc method")
|
return nil, fmt.Errorf("Error from grpc method: %w", err)
|
||||||
}
|
}
|
||||||
} else if operation == OpKeyUnwrap {
|
} else if operation == OpKeyUnwrap {
|
||||||
grpcOutput, err = client.UnWrapKey(context.Background(), req)
|
grpcOutput, err = client.UnWrapKey(context.Background(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Error from grpc method")
|
return nil, fmt.Errorf("Error from grpc method: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.New("Unsupported operation")
|
return nil, errors.New("Unsupported operation")
|
||||||
|
@ -201,7 +201,7 @@ func getProviderGRPCOutput(input []byte, connString string, operation KeyProvide
|
||||||
respBytes := grpcOutput.GetKeyProviderKeyWrapProtocolOutput()
|
respBytes := grpcOutput.GetKeyProviderKeyWrapProtocolOutput()
|
||||||
err = json.Unmarshal(respBytes, &protocolOuput)
|
err = json.Unmarshal(respBytes, &protocolOuput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Error while unmarshalling grpc method output")
|
return nil, fmt.Errorf("Error while unmarshalling grpc method output: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &protocolOuput, nil
|
return &protocolOuput, nil
|
||||||
|
@ -216,7 +216,7 @@ func getProviderCommandOutput(input []byte, command *keyproviderconfig.Command)
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(respBytes, &protocolOuput)
|
err = json.Unmarshal(respBytes, &protocolOuput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Error while unmarshalling binary executable command output")
|
return nil, fmt.Errorf("Error while unmarshalling binary executable command output: %w", err)
|
||||||
}
|
}
|
||||||
return &protocolOuput, nil
|
return &protocolOuput, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,28 +24,29 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/containers/ocicrypt/config"
|
"github.com/containers/ocicrypt/config"
|
||||||
keyprovider_config "github.com/containers/ocicrypt/config/keyprovider-config"
|
keyprovider_config "github.com/containers/ocicrypt/config/keyprovider-config"
|
||||||
keyproviderpb "github.com/containers/ocicrypt/utils/keyprovider"
|
keyproviderpb "github.com/containers/ocicrypt/utils/keyprovider"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//Test runner which mocks binary executable for key wrapping and unwrapping
|
// TestRunner mocks binary executable for key wrapping and unwrapping
|
||||||
type TestRunner struct{}
|
type TestRunner struct{}
|
||||||
|
|
||||||
//Mock annotation packet, which goes into container image manifest
|
// Mock annotation packet, which goes into container image manifest
|
||||||
type annotationPacket struct {
|
type annotationPacket struct {
|
||||||
KeyUrl string `json:"key_url"`
|
KeyUrl string `json:"key_url"`
|
||||||
WrappedKey []byte `json:"wrapped_key"`
|
WrappedKey []byte `json:"wrapped_key"`
|
||||||
WrapType string `json:"wrap_type"`
|
WrapType string `json:"wrap_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//grpc server with mock api implementation for serving the clients with mock WrapKey and Unwrapkey grpc method implementations
|
// grpc server with mock api implementation for serving the clients with mock WrapKey and Unwrapkey grpc method implementations
|
||||||
type server struct {
|
type server struct {
|
||||||
keyproviderpb.UnimplementedKeyProviderServiceServer
|
keyproviderpb.UnimplementedKeyProviderServiceServer
|
||||||
}
|
}
|
||||||
|
@ -68,14 +69,14 @@ func init() {
|
||||||
func (*server) WrapKey(ctx context.Context, request *keyproviderpb.KeyProviderKeyWrapProtocolInput) (*keyproviderpb.KeyProviderKeyWrapProtocolOutput, error) {
|
func (*server) WrapKey(ctx context.Context, request *keyproviderpb.KeyProviderKeyWrapProtocolInput) (*keyproviderpb.KeyProviderKeyWrapProtocolOutput, error) {
|
||||||
var keyP KeyProviderKeyWrapProtocolInput
|
var keyP KeyProviderKeyWrapProtocolInput
|
||||||
err := json.Unmarshal(request.KeyProviderKeyWrapProtocolInput, &keyP)
|
err := json.Unmarshal(request.KeyProviderKeyWrapProtocolInput, &keyP)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c, _ := aes.NewCipher(encryptingKey)
|
c, _ := aes.NewCipher(encryptingKey)
|
||||||
gcm, _ := cipher.NewGCM(c)
|
gcm, _ := cipher.NewGCM(c)
|
||||||
nonce := make([]byte, gcm.NonceSize())
|
nonce := make([]byte, gcm.NonceSize())
|
||||||
_, err = io.ReadFull(rand.Reader, nonce)
|
_, err = io.ReadFull(rand.Reader, nonce)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,12 +101,12 @@ func (*server) WrapKey(ctx context.Context, request *keyproviderpb.KeyProviderKe
|
||||||
func (*server) UnWrapKey(ctx context.Context, request *keyproviderpb.KeyProviderKeyWrapProtocolInput) (*keyproviderpb.KeyProviderKeyWrapProtocolOutput, error) {
|
func (*server) UnWrapKey(ctx context.Context, request *keyproviderpb.KeyProviderKeyWrapProtocolInput) (*keyproviderpb.KeyProviderKeyWrapProtocolOutput, error) {
|
||||||
var keyP KeyProviderKeyWrapProtocolInput
|
var keyP KeyProviderKeyWrapProtocolInput
|
||||||
err := json.Unmarshal(request.KeyProviderKeyWrapProtocolInput, &keyP)
|
err := json.Unmarshal(request.KeyProviderKeyWrapProtocolInput, &keyP)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
apkt := annotationPacket{}
|
apkt := annotationPacket{}
|
||||||
err = json.Unmarshal(keyP.KeyUnwrapParams.Annotation, &apkt)
|
err = json.Unmarshal(keyP.KeyUnwrapParams.Annotation, &apkt)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ciphertext := apkt.WrappedKey
|
ciphertext := apkt.WrappedKey
|
||||||
|
@ -133,7 +134,7 @@ func (r TestRunner) Exec(cmdName string, args []string, input []byte) ([]byte, e
|
||||||
if cmdName == "/usr/lib/keyprovider-1-wrapkey" {
|
if cmdName == "/usr/lib/keyprovider-1-wrapkey" {
|
||||||
var keyP KeyProviderKeyWrapProtocolInput
|
var keyP KeyProviderKeyWrapProtocolInput
|
||||||
err := json.Unmarshal(input, &keyP)
|
err := json.Unmarshal(input, &keyP)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c, _ := aes.NewCipher(encryptingKey)
|
c, _ := aes.NewCipher(encryptingKey)
|
||||||
|
@ -141,7 +142,7 @@ func (r TestRunner) Exec(cmdName string, args []string, input []byte) ([]byte, e
|
||||||
|
|
||||||
nonce := make([]byte, gcm.NonceSize())
|
nonce := make([]byte, gcm.NonceSize())
|
||||||
_, err = io.ReadFull(rand.Reader, nonce)
|
_, err = io.ReadFull(rand.Reader, nonce)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
wrappedKey := gcm.Seal(nonce, nonce, keyP.KeyWrapParams.OptsData, nil)
|
wrappedKey := gcm.Seal(nonce, nonce, keyP.KeyWrapParams.OptsData, nil)
|
||||||
|
@ -160,12 +161,12 @@ func (r TestRunner) Exec(cmdName string, args []string, input []byte) ([]byte, e
|
||||||
} else if cmdName == "/usr/lib/keyprovider-1-unwrapkey" {
|
} else if cmdName == "/usr/lib/keyprovider-1-unwrapkey" {
|
||||||
var keyP KeyProviderKeyWrapProtocolInput
|
var keyP KeyProviderKeyWrapProtocolInput
|
||||||
err := json.Unmarshal(input, &keyP)
|
err := json.Unmarshal(input, &keyP)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
apkt := annotationPacket{}
|
apkt := annotationPacket{}
|
||||||
err = json.Unmarshal(keyP.KeyUnwrapParams.Annotation, &apkt)
|
err = json.Unmarshal(keyP.KeyUnwrapParams.Annotation, &apkt)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ciphertext := apkt.WrappedKey
|
ciphertext := apkt.WrappedKey
|
||||||
|
@ -183,7 +184,7 @@ func (r TestRunner) Exec(cmdName string, args []string, input []byte) ([]byte, e
|
||||||
KeyUnwrapResults: KeyUnwrapResults{OptsData: unwrappedKey},
|
KeyUnwrapResults: KeyUnwrapResults{OptsData: unwrappedKey},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nil, errors.New("unkown protocol")
|
return nil, errors.New("unknown protocol")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeyWrapKeyProviderCommandSuccess(t *testing.T) {
|
func TestKeyWrapKeyProviderCommandSuccess(t *testing.T) {
|
||||||
|
@ -364,7 +365,6 @@ func TestKeyWrapKeyProviderGRPCSuccess(t *testing.T) {
|
||||||
keyWrapOutput, err := keyWrapper.WrapKeys(&ec, optsData)
|
keyWrapOutput, err := keyWrapper.WrapKeys(&ec, optsData)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
||||||
dp := make(map[string][][]byte)
|
dp := make(map[string][][]byte)
|
||||||
dp["keyprovider-1"] = append(dp["keyprovider-1"], []byte("Supported Protocol"))
|
dp["keyprovider-1"] = append(dp["keyprovider-1"], []byte("Supported Protocol"))
|
||||||
|
|
||||||
|
@ -376,5 +376,3 @@ func TestKeyWrapKeyProviderGRPCSuccess(t *testing.T) {
|
||||||
assert.Equal(t, optsData, keyUnWrapOutput)
|
assert.Equal(t, optsData, keyUnWrapOutput)
|
||||||
os.Remove(path)
|
os.Remove(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,16 +21,15 @@ import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containers/ocicrypt/config"
|
"github.com/containers/ocicrypt/config"
|
||||||
"github.com/containers/ocicrypt/keywrap"
|
"github.com/containers/ocicrypt/keywrap"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/crypto/openpgp"
|
"golang.org/x/crypto/openpgp"
|
||||||
"golang.org/x/crypto/openpgp/packet"
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
)
|
)
|
||||||
|
@ -64,7 +63,7 @@ func (kw *gpgKeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]
|
||||||
ciphertext := new(bytes.Buffer)
|
ciphertext := new(bytes.Buffer)
|
||||||
el, err := kw.createEntityList(ec)
|
el, err := kw.createEntityList(ec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "unable to create entity list")
|
return nil, fmt.Errorf("unable to create entity list: %w", err)
|
||||||
}
|
}
|
||||||
if len(el) == 0 {
|
if len(el) == 0 {
|
||||||
// nothing to do -- not an error
|
// nothing to do -- not an error
|
||||||
|
@ -100,7 +99,7 @@ func (kw *gpgKeyWrapper) UnwrapKey(dc *config.DecryptConfig, pgpPacket []byte) (
|
||||||
r := bytes.NewBuffer(pgpPrivateKey)
|
r := bytes.NewBuffer(pgpPrivateKey)
|
||||||
entityList, err := openpgp.ReadKeyRing(r)
|
entityList, err := openpgp.ReadKeyRing(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "unable to parse private keys")
|
return nil, fmt.Errorf("unable to parse private keys: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var prompt openpgp.PromptFunction
|
var prompt openpgp.PromptFunction
|
||||||
|
@ -126,7 +125,7 @@ func (kw *gpgKeyWrapper) UnwrapKey(dc *config.DecryptConfig, pgpPacket []byte) (
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// we get the plain key options back
|
// we get the plain key options back
|
||||||
optsData, err := ioutil.ReadAll(md.UnverifiedBody)
|
optsData, err := io.ReadAll(md.UnverifiedBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -142,7 +141,7 @@ func (kw *gpgKeyWrapper) GetKeyIdsFromPacket(b64pgpPackets string) ([]uint64, er
|
||||||
for _, b64pgpPacket := range strings.Split(b64pgpPackets, ",") {
|
for _, b64pgpPacket := range strings.Split(b64pgpPackets, ",") {
|
||||||
pgpPacket, err := base64.StdEncoding.DecodeString(b64pgpPacket)
|
pgpPacket, err := base64.StdEncoding.DecodeString(b64pgpPacket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not decode base64 encoded PGP packet")
|
return nil, fmt.Errorf("could not decode base64 encoded PGP packet: %w", err)
|
||||||
}
|
}
|
||||||
newids, err := kw.getKeyIDs(pgpPacket)
|
newids, err := kw.getKeyIDs(pgpPacket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -166,7 +165,7 @@ ParsePackets:
|
||||||
break ParsePackets
|
break ParsePackets
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []uint64{}, errors.Wrapf(err, "packets.Next() failed")
|
return []uint64{}, fmt.Errorf("packets.Next() failed: %w", err)
|
||||||
}
|
}
|
||||||
switch p := p.(type) {
|
switch p := p.(type) {
|
||||||
case *packet.EncryptedKey:
|
case *packet.EncryptedKey:
|
||||||
|
|
|
@ -17,12 +17,13 @@
|
||||||
package pkcs11
|
package pkcs11
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/containers/ocicrypt/config"
|
"github.com/containers/ocicrypt/config"
|
||||||
"github.com/containers/ocicrypt/crypto/pkcs11"
|
"github.com/containers/ocicrypt/crypto/pkcs11"
|
||||||
"github.com/containers/ocicrypt/keywrap"
|
"github.com/containers/ocicrypt/keywrap"
|
||||||
"github.com/containers/ocicrypt/utils"
|
"github.com/containers/ocicrypt/utils"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type pkcs11KeyWrapper struct {
|
type pkcs11KeyWrapper struct {
|
||||||
|
@ -40,7 +41,11 @@ func NewKeyWrapper() keywrap.KeyWrapper {
|
||||||
// WrapKeys wraps the session key for recpients and encrypts the optsData, which
|
// WrapKeys wraps the session key for recpients and encrypts the optsData, which
|
||||||
// describe the symmetric key used for encrypting the layer
|
// describe the symmetric key used for encrypting the layer
|
||||||
func (kw *pkcs11KeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
|
func (kw *pkcs11KeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
|
||||||
pkcs11Recipients, err := addPubKeys(&ec.DecryptConfig, append(ec.Parameters["pkcs11-pubkeys"], ec.Parameters["pkcs11-yamls"]...))
|
// append({}, ...) allocates a fresh backing array, and that's necessary to guarantee concurrent calls to WrapKeys (as in c/image/copy.Image)
|
||||||
|
// can't race writing to the same backing array.
|
||||||
|
pubKeys := append([][]byte{}, ec.Parameters["pkcs11-pubkeys"]...) // In Go 1.21, slices.Clone(ec.Parameters["pkcs11-pubkeys"])
|
||||||
|
pubKeys = append(pubKeys, ec.Parameters["pkcs11-yamls"]...)
|
||||||
|
pkcs11Recipients, err := addPubKeys(&ec.DecryptConfig, pubKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -51,7 +56,7 @@ func (kw *pkcs11KeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte)
|
||||||
|
|
||||||
jsonString, err := pkcs11.EncryptMultiple(pkcs11Recipients, optsData)
|
jsonString, err := pkcs11.EncryptMultiple(pkcs11Recipients, optsData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "PKCS11 EncryptMulitple failed")
|
return nil, fmt.Errorf("PKCS11 EncryptMulitple failed: %w", err)
|
||||||
}
|
}
|
||||||
return jsonString, nil
|
return jsonString, nil
|
||||||
}
|
}
|
||||||
|
@ -91,7 +96,7 @@ func (kw *pkcs11KeyWrapper) UnwrapKey(dc *config.DecryptConfig, jsonString []byt
|
||||||
return plaintext, nil
|
return plaintext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.Wrapf(err, "PKCS11: No suitable private key found for decryption")
|
return nil, fmt.Errorf("PKCS11: No suitable private key found for decryption: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kw *pkcs11KeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool {
|
func (kw *pkcs11KeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool {
|
||||||
|
@ -139,7 +144,7 @@ func addPubKeys(dc *config.DecryptConfig, pubKeys [][]byte) ([]interface{}, erro
|
||||||
return pkcs11Keys, nil
|
return pkcs11Keys, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func p11confFromParameters(dcparameters map[string][][]byte) (*pkcs11.Pkcs11Config, error){
|
func p11confFromParameters(dcparameters map[string][][]byte) (*pkcs11.Pkcs11Config, error) {
|
||||||
if _, ok := dcparameters["pkcs11-config"]; ok {
|
if _, ok := dcparameters["pkcs11-config"]; ok {
|
||||||
return pkcs11.ParsePkcs11ConfigFile(dcparameters["pkcs11-config"][0])
|
return pkcs11.ParsePkcs11ConfigFile(dcparameters["pkcs11-config"][0])
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containers/ocicrypt/config"
|
"github.com/containers/ocicrypt/config"
|
||||||
"github.com/containers/ocicrypt/utils"
|
|
||||||
"github.com/containers/ocicrypt/crypto/pkcs11"
|
"github.com/containers/ocicrypt/crypto/pkcs11"
|
||||||
|
"github.com/containers/ocicrypt/utils"
|
||||||
"github.com/containers/ocicrypt/utils/softhsm"
|
"github.com/containers/ocicrypt/utils/softhsm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ module:
|
||||||
{
|
{
|
||||||
EncryptConfig: &config.EncryptConfig{
|
EncryptConfig: &config.EncryptConfig{
|
||||||
Parameters: map[string][][]byte{
|
Parameters: map[string][][]byte{
|
||||||
"pkcs11-pubkeys": {[]byte(pubKey2Pem)},
|
"pkcs11-pubkeys": {pubKey2Pem},
|
||||||
},
|
},
|
||||||
DecryptConfig: config.DecryptConfig{
|
DecryptConfig: config.DecryptConfig{
|
||||||
Parameters: map[string][][]byte{
|
Parameters: map[string][][]byte{
|
||||||
|
|
|
@ -19,12 +19,13 @@ package pkcs7
|
||||||
import (
|
import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"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/pkg/errors"
|
"github.com/smallstep/pkcs7"
|
||||||
"go.mozilla.org/pkcs7"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type pkcs7KeyWrapper struct {
|
type pkcs7KeyWrapper struct {
|
||||||
|
@ -104,7 +105,7 @@ func (kw *pkcs7KeyWrapper) UnwrapKey(dc *config.DecryptConfig, pkcs7Packet []byt
|
||||||
|
|
||||||
p7, err := pkcs7.Parse(pkcs7Packet)
|
p7, err := pkcs7.Parse(pkcs7Packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not parse PKCS7 packet")
|
return nil, fmt.Errorf("could not parse PKCS7 packet: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, privKey := range privKeys {
|
for idx, privKey := range privKeys {
|
||||||
|
|
12
spec/spec.go
12
spec/spec.go
|
@ -3,10 +3,18 @@ package spec
|
||||||
const (
|
const (
|
||||||
// MediaTypeLayerEnc is MIME type used for encrypted layers.
|
// MediaTypeLayerEnc is MIME type used for encrypted layers.
|
||||||
MediaTypeLayerEnc = "application/vnd.oci.image.layer.v1.tar+encrypted"
|
MediaTypeLayerEnc = "application/vnd.oci.image.layer.v1.tar+encrypted"
|
||||||
// MediaTypeLayerGzipEnc is MIME type used for encrypted compressed layers.
|
// MediaTypeLayerGzipEnc is MIME type used for encrypted gzip-compressed layers.
|
||||||
MediaTypeLayerGzipEnc = "application/vnd.oci.image.layer.v1.tar+gzip+encrypted"
|
MediaTypeLayerGzipEnc = "application/vnd.oci.image.layer.v1.tar+gzip+encrypted"
|
||||||
|
// MediaTypeLayerZstdEnc is MIME type used for encrypted zstd-compressed layers.
|
||||||
|
MediaTypeLayerZstdEnc = "application/vnd.oci.image.layer.v1.tar+zstd+encrypted"
|
||||||
// MediaTypeLayerNonDistributableEnc is MIME type used for non distributable encrypted layers.
|
// MediaTypeLayerNonDistributableEnc is MIME type used for non distributable encrypted layers.
|
||||||
MediaTypeLayerNonDistributableEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+encrypted"
|
MediaTypeLayerNonDistributableEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+encrypted"
|
||||||
// MediaTypeLayerGzipEnc is MIME type used for non distributable encrypted compressed layers.
|
// MediaTypeLayerNonDistributableGzipEnc is MIME type used for non distributable encrypted gzip-compressed layers.
|
||||||
MediaTypeLayerNonDistributableGzipEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip+encrypted"
|
MediaTypeLayerNonDistributableGzipEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip+encrypted"
|
||||||
|
// MediaTypeLayerNonDistributableZstdEnc is MIME type used for non distributable encrypted zstd-compressed layers.
|
||||||
|
MediaTypeLayerNonDistributableZstdEnc = "application/vnd.oci.image.layer.nondistributable.v1.tar+zstd+encrypted"
|
||||||
|
// MediaTypeLayerNonDistributableZsdtEnc is MIME type used for non distributable encrypted zstd-compressed layers.
|
||||||
|
//
|
||||||
|
// Deprecated: Use [MediaTypeLayerNonDistributableZstdEnc].
|
||||||
|
MediaTypeLayerNonDistributableZsdtEnc = MediaTypeLayerNonDistributableZstdEnc
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,9 +18,9 @@ package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FillBuffer fills the given buffer with as many bytes from the reader as possible. It returns
|
// FillBuffer fills the given buffer with as many bytes from the reader as possible. It returns
|
||||||
|
@ -44,13 +44,15 @@ type Runner struct{}
|
||||||
// ExecuteCommand is used to execute a linux command line command and return the output of the command with an error if it exists.
|
// ExecuteCommand is used to execute a linux command line command and return the output of the command with an error if it exists.
|
||||||
func (r Runner) Exec(cmdName string, args []string, input []byte) ([]byte, error) {
|
func (r Runner) Exec(cmdName string, args []string, input []byte) ([]byte, error) {
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
|
var stderr bytes.Buffer
|
||||||
stdInputBuffer := bytes.NewBuffer(input)
|
stdInputBuffer := bytes.NewBuffer(input)
|
||||||
cmd := exec.Command(cmdName, args...)
|
cmd := exec.Command(cmdName, args...)
|
||||||
cmd.Stdin = stdInputBuffer
|
cmd.Stdin = stdInputBuffer
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
|
cmd.Stderr = &stderr
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "Error while running command: %s", cmdName)
|
return nil, fmt.Errorf("Error while running command: %s. stderr: %s: %w", cmdName, stderr.String(), err)
|
||||||
}
|
}
|
||||||
return out.Bytes(), nil
|
return out.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,11 @@ package softhsm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SoftHSMSetup struct {
|
type SoftHSMSetup struct {
|
||||||
|
@ -42,9 +41,9 @@ func (s *SoftHSMSetup) GetConfigFilename() string {
|
||||||
|
|
||||||
// RunSoftHSMSetup runs 'softhsm_setup setup' and returns the public key that was displayed
|
// RunSoftHSMSetup runs 'softhsm_setup setup' and returns the public key that was displayed
|
||||||
func (s *SoftHSMSetup) RunSoftHSMSetup(softhsmSetup string) (string, error) {
|
func (s *SoftHSMSetup) RunSoftHSMSetup(softhsmSetup string) (string, error) {
|
||||||
statedir, err := ioutil.TempDir("", "ocicrypt")
|
statedir, err := os.MkdirTemp("", "ocicrypt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrapf(err, "Could not create temporary directory fot softhsm state")
|
return "", fmt.Errorf("Could not create temporary directory fot softhsm state: %w", err)
|
||||||
}
|
}
|
||||||
s.statedir = statedir
|
s.statedir = statedir
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ func (s *SoftHSMSetup) RunSoftHSMSetup(softhsmSetup string) (string, error) {
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.RemoveAll(s.statedir)
|
os.RemoveAll(s.statedir)
|
||||||
return "", errors.Wrapf(err, "%s setup failed: %s", softhsmSetup, out.String())
|
return "", fmt.Errorf("%s setup failed: %s: %w", softhsmSetup, out.String(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
o := out.String()
|
o := out.String()
|
||||||
|
@ -76,7 +75,7 @@ func (s *SoftHSMSetup) RunSoftHSMGetPubkey(softhsmSetup string) (string, error)
|
||||||
cmd.Env = append(cmd.Env, "SOFTHSM_SETUP_CONFIGDIR="+s.statedir)
|
cmd.Env = append(cmd.Env, "SOFTHSM_SETUP_CONFIGDIR="+s.statedir)
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrapf(err, "%s getpubkey failed: %s", softhsmSetup, out.String())
|
return "", fmt.Errorf("%s getpubkey failed: %s: %w", softhsmSetup, out.String(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return out.String(), nil
|
return out.String(), nil
|
||||||
|
|
|
@ -24,17 +24,25 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateRSAKey creates an RSA key
|
// CreateRSAKey creates an RSA key
|
||||||
func CreateRSAKey(bits int) (*rsa.PrivateKey, error) {
|
func CreateRSAKey(bits int) (*rsa.PrivateKey, error) {
|
||||||
key, err := rsa.GenerateKey(rand.Reader, bits)
|
key, err := rsa.GenerateKey(rand.Reader, bits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "rsa.GenerateKey failed")
|
return nil, fmt.Errorf("rsa.GenerateKey failed: %w", err)
|
||||||
|
}
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateECDSAKey creates an elliptic curve key for the given curve
|
||||||
|
func CreateECDSAKey(curve elliptic.Curve) (*ecdsa.PrivateKey, error) {
|
||||||
|
key, err := ecdsa.GenerateKey(curve, rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("ecdsa.GenerateKey failed: %w", err)
|
||||||
}
|
}
|
||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
@ -49,7 +57,7 @@ func CreateRSATestKey(bits int, password []byte, pemencode bool) ([]byte, []byte
|
||||||
|
|
||||||
pubData, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
|
pubData, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "x509.MarshalPKIXPublicKey failed")
|
return nil, nil, fmt.Errorf("x509.MarshalPKIXPublicKey failed: %w", err)
|
||||||
}
|
}
|
||||||
privData := x509.MarshalPKCS1PrivateKey(key)
|
privData := x509.MarshalPKCS1PrivateKey(key)
|
||||||
|
|
||||||
|
@ -69,7 +77,7 @@ func CreateRSATestKey(bits int, password []byte, pemencode bool) ([]byte, []byte
|
||||||
if len(password) > 0 {
|
if len(password) > 0 {
|
||||||
block, err = x509.EncryptPEMBlock(rand.Reader, typ, privData, password, x509.PEMCipherAES256) //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility
|
block, err = x509.EncryptPEMBlock(rand.Reader, typ, privData, password, x509.PEMCipherAES256) //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "x509.EncryptPEMBlock failed")
|
return nil, nil, fmt.Errorf("x509.EncryptPEMBlock failed: %w", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
block = &pem.Block{
|
block = &pem.Block{
|
||||||
|
@ -86,19 +94,19 @@ func CreateRSATestKey(bits int, password []byte, pemencode bool) ([]byte, []byte
|
||||||
// CreateECDSATestKey creates and elliptic curve key for the given curve and returns
|
// CreateECDSATestKey creates and elliptic curve key for the given curve and returns
|
||||||
// the public and private key in DER format
|
// the public and private key in DER format
|
||||||
func CreateECDSATestKey(curve elliptic.Curve) ([]byte, []byte, error) {
|
func CreateECDSATestKey(curve elliptic.Curve) ([]byte, []byte, error) {
|
||||||
key, err := ecdsa.GenerateKey(curve, rand.Reader)
|
key, err := CreateECDSAKey(curve)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrapf(err, "ecdsa.GenerateKey failed")
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pubData, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
|
pubData, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrapf(err, "x509.MarshalPKIXPublicKey failed")
|
return nil, nil, fmt.Errorf("x509.MarshalPKIXPublicKey failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
privData, err := x509.MarshalECPrivateKey(key)
|
privData, err := x509.MarshalECPrivateKey(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrapf(err, "x509.MarshalECPrivateKey failed")
|
return nil, nil, fmt.Errorf("x509.MarshalECPrivateKey failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pubData, privData, nil
|
return pubData, privData, nil
|
||||||
|
@ -108,7 +116,7 @@ func CreateECDSATestKey(curve elliptic.Curve) ([]byte, []byte, error) {
|
||||||
func CreateTestCA() (*rsa.PrivateKey, *x509.Certificate, error) {
|
func CreateTestCA() (*rsa.PrivateKey, *x509.Certificate, error) {
|
||||||
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "rsa.GenerateKey failed")
|
return nil, nil, fmt.Errorf("rsa.GenerateKey failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ca := &x509.Certificate{
|
ca := &x509.Certificate{
|
||||||
|
@ -154,12 +162,12 @@ func certifyKey(pub interface{}, template *x509.Certificate, caKey *rsa.PrivateK
|
||||||
|
|
||||||
certDER, err := x509.CreateCertificate(rand.Reader, template, caCert, pub, caKey)
|
certDER, err := x509.CreateCertificate(rand.Reader, template, caCert, pub, caKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "x509.CreateCertificate failed")
|
return nil, fmt.Errorf("x509.CreateCertificate failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cert, err := x509.ParseCertificate(certDER)
|
cert, err := x509.ParseCertificate(certDER)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "x509.ParseCertificate failed")
|
return nil, fmt.Errorf("x509.ParseCertificate failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cert, nil
|
return cert, nil
|
||||||
|
|
|
@ -21,22 +21,21 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containers/ocicrypt/crypto/pkcs11"
|
"github.com/containers/ocicrypt/crypto/pkcs11"
|
||||||
|
"github.com/go-jose/go-jose/v4"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/crypto/openpgp"
|
"golang.org/x/crypto/openpgp"
|
||||||
json "gopkg.in/square/go-jose.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// parseJWKPrivateKey parses the input byte array as a JWK and makes sure it's a private key
|
// parseJWKPrivateKey parses the input byte array as a JWK and makes sure it's a private key
|
||||||
func parseJWKPrivateKey(privKey []byte, prefix string) (interface{}, error) {
|
func parseJWKPrivateKey(privKey []byte, prefix string) (interface{}, error) {
|
||||||
jwk := json.JSONWebKey{}
|
jwk := jose.JSONWebKey{}
|
||||||
err := jwk.UnmarshalJSON(privKey)
|
err := jwk.UnmarshalJSON(privKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "%s: Could not parse input as JWK", prefix)
|
return nil, fmt.Errorf("%s: Could not parse input as JWK: %w", prefix, err)
|
||||||
}
|
}
|
||||||
if jwk.IsPublic() {
|
if jwk.IsPublic() {
|
||||||
return nil, fmt.Errorf("%s: JWK is not a private key", prefix)
|
return nil, fmt.Errorf("%s: JWK is not a private key", prefix)
|
||||||
|
@ -46,10 +45,10 @@ func parseJWKPrivateKey(privKey []byte, prefix string) (interface{}, error) {
|
||||||
|
|
||||||
// parseJWKPublicKey parses the input byte array as a JWK
|
// parseJWKPublicKey parses the input byte array as a JWK
|
||||||
func parseJWKPublicKey(privKey []byte, prefix string) (interface{}, error) {
|
func parseJWKPublicKey(privKey []byte, prefix string) (interface{}, error) {
|
||||||
jwk := json.JSONWebKey{}
|
jwk := jose.JSONWebKey{}
|
||||||
err := jwk.UnmarshalJSON(privKey)
|
err := jwk.UnmarshalJSON(privKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "%s: Could not parse input as JWK", prefix)
|
return nil, fmt.Errorf("%s: Could not parse input as JWK: %w", prefix, err)
|
||||||
}
|
}
|
||||||
if !jwk.IsPublic() {
|
if !jwk.IsPublic() {
|
||||||
return nil, fmt.Errorf("%s: JWK is not a public key", prefix)
|
return nil, fmt.Errorf("%s: JWK is not a public key", prefix)
|
||||||
|
@ -97,11 +96,11 @@ func ParsePrivateKey(privKey, privKeyPassword []byte, prefix string) (interface{
|
||||||
var der []byte
|
var der []byte
|
||||||
if x509.IsEncryptedPEMBlock(block) { //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility
|
if x509.IsEncryptedPEMBlock(block) { //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility
|
||||||
if privKeyPassword == nil {
|
if privKeyPassword == nil {
|
||||||
return nil, errors.Errorf("%s: Missing password for encrypted private key", prefix)
|
return nil, fmt.Errorf("%s: Missing password for encrypted private key", prefix)
|
||||||
}
|
}
|
||||||
der, err = x509.DecryptPEMBlock(block, privKeyPassword) //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility
|
der, err = x509.DecryptPEMBlock(block, privKeyPassword) //nolint:staticcheck // ignore SA1019, which is kept for backward compatibility
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("%s: Wrong password: could not decrypt private key", prefix)
|
return nil, fmt.Errorf("%s: Wrong password: could not decrypt private key", prefix)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
der = block.Bytes
|
der = block.Bytes
|
||||||
|
@ -111,7 +110,7 @@ func ParsePrivateKey(privKey, privKeyPassword []byte, prefix string) (interface{
|
||||||
if err != nil {
|
if err != nil {
|
||||||
key, err = x509.ParsePKCS1PrivateKey(der)
|
key, err = x509.ParsePKCS1PrivateKey(der)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "%s: Could not parse private key", prefix)
|
return nil, fmt.Errorf("%s: Could not parse private key: %w", prefix, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -145,7 +144,7 @@ func ParsePublicKey(pubKey []byte, prefix string) (interface{}, error) {
|
||||||
if block != nil {
|
if block != nil {
|
||||||
key, err = x509.ParsePKIXPublicKey(block.Bytes)
|
key, err = x509.ParsePKIXPublicKey(block.Bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "%s: Could not parse public key", prefix)
|
return nil, fmt.Errorf("%s: Could not parse public key: %w", prefix, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
key, err = parseJWKPublicKey(pubKey, prefix)
|
key, err = parseJWKPublicKey(pubKey, prefix)
|
||||||
|
@ -179,7 +178,7 @@ func ParseCertificate(certBytes []byte, prefix string) (*x509.Certificate, error
|
||||||
}
|
}
|
||||||
x509Cert, err = x509.ParseCertificate(block.Bytes)
|
x509Cert, err = x509.ParseCertificate(block.Bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "%s: Could not parse x509 certificate", prefix)
|
return nil, fmt.Errorf("%s: Could not parse x509 certificate: %w", prefix, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x509Cert, err
|
return x509Cert, err
|
||||||
|
|
Loading…
Reference in New Issue