Compare commits

..

No commits in common. "main" and "v1.1.4" have entirely different histories.
main ... v1.1.4

37 changed files with 393 additions and 615 deletions

View File

@ -1,74 +0,0 @@
# 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}}"

View File

@ -1,40 +0,0 @@
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

1
.gitignore vendored
View File

@ -1 +0,0 @@
*~

View File

@ -1,47 +0,0 @@
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 Normal file
View File

@ -0,0 +1,29 @@
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

View File

@ -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/main/CODE-OF-CONDUCT.md). The OCIcrypt Library project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md).

View File

@ -28,7 +28,6 @@ vendor:
go mod tidy go mod tidy
test: test:
go clean -testcache
go test ./... -test.v go test ./... -test.v
generate-protobuf: generate-protobuf:

View File

@ -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/main/SECURITY.md) for the Containers Projects. The OCIcrypt Library Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/master/SECURITY.md) for the Containers Projects.

View File

@ -17,11 +17,10 @@
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
@ -96,8 +95,9 @@ 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, fmt.Errorf("unsupported cipher type: %s", typ) return nil, nil, errors.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[typ]; ok { if c, ok := h.cipherMap[LayerCipherType(typ)]; ok {
return c.Decrypt(encDataReader, opt) return c.Decrypt(encDataReader, opt)
} }
return nil, LayerBlockCipherOptions{}, fmt.Errorf("unsupported cipher type: %s", typ) return nil, LayerBlockCipherOptions{}, errors.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, fmt.Errorf("unable to set up Cipher AES-256-CTR: %w", err) return nil, errors.Wrap(err, "unable to set up Cipher AES-256-CTR")
} }
return &h, nil return &h, nil

View File

@ -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 = fmt.Errorf("could not write to hmac: %w", err) r.bc.err = errors.Wrapf(err, "could not write to hmac")
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 = fmt.Errorf("could not write to hmac: %w", err) r.bc.err = errors.Wrapf(err, "could not write to hmac")
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{}, fmt.Errorf("unable to generate random nonce: %w", err) return LayerBlockCipherOptions{}, errors.Wrap(err, "unable to generate random nonce")
} }
} }
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
return LayerBlockCipherOptions{}, fmt.Errorf("aes.NewCipher failed: %w", err) return LayerBlockCipherOptions{}, errors.Wrap(err, "aes.NewCipher failed")
} }
bc.reader = reader bc.reader = reader

View File

@ -17,12 +17,11 @@
package config package config
import ( import (
"errors" "github.com/containers/ocicrypt/crypto/pkcs11"
"fmt"
"strings" "strings"
"github.com/containers/ocicrypt/crypto/pkcs11" "github.com/pkg/errors"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v2"
) )
// EncryptWithJwe returns a CryptoConfig to encrypt with jwe public keys // EncryptWithJwe returns a CryptoConfig to encrypt with jwe public keys
@ -86,7 +85,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{}, fmt.Errorf("Could not marshal Pkcs11Config to Yaml: %w", err) return CryptoConfig{}, errors.Wrapf(err, "Could not marshal Pkcs11Config to Yaml")
} }
dc = DecryptConfig{ dc = DecryptConfig{
@ -224,7 +223,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{}, fmt.Errorf("Could not marshal Pkcs11Config to Yaml: %w", err) return CryptoConfig{}, errors.Wrapf(err, "Could not marshal Pkcs11Config to Yaml")
} }
dc := DecryptConfig{ dc := DecryptConfig{

View File

@ -18,7 +18,8 @@ package config
import ( import (
"encoding/json" "encoding/json"
"fmt" "github.com/pkg/errors"
"io/ioutil"
"os" "os"
) )
@ -51,7 +52,7 @@ func parseConfigFile(filename string) (*OcicryptConfig, error) {
return nil, nil return nil, nil
} }
data, err := os.ReadFile(filename) data, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -71,7 +72,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, fmt.Errorf("Error while parsing keyprovider config file: %w", err) return nil, errors.Wrap(err, "Error while parsing keyprovider config file")
} }
} else { } else {
return nil, nil return nil, nil

View File

@ -17,13 +17,14 @@
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"
"gopkg.in/yaml.v3" "github.com/pkg/errors"
"gopkg.in/yaml.v2"
) )
// OcicryptConfig represents the format of an imgcrypt.conf config file // OcicryptConfig represents the format of an imgcrypt.conf config file
@ -38,11 +39,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)
@ -50,7 +51,7 @@ func parseConfigFile(filename string) (*OcicryptConfig, error) {
return nil, nil return nil, nil
} }
data, err := os.ReadFile(filename) data, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -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.v3" "gopkg.in/yaml.v2"
) )
// 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, fmt.Errorf("Could not parse Pkcs11URI from file: %w", err) return nil, errors.Wrapf(err, "Could not parse Pkcs11URI from file")
} }
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(yamlstr, &p11keyfile) err := yaml.Unmarshal([]byte(yamlstr), &p11keyfile)
if err != nil { if err != nil {
return nil, fmt.Errorf("Could not unmarshal pkcs11 keyfile: %w", err) return nil, errors.Wrapf(err, "Could not unmarshal pkcs11 keyfile")
} }
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|riscv64|s390x)-linux-gnu/ // Debian directory: /usr/lib/(x86_64|aarch64|arm|powerpc64le|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(yamlstr, &p11conf) err := yaml.Unmarshal([]byte(yamlstr), &p11conf)
if err != nil { if err != nil {
return &p11conf, fmt.Errorf("Could not parse Pkcs11Config: %w", err) return &p11conf, errors.Wrapf(err, "Could not parse Pkcs11Config")
} }
return &p11conf, nil return &p11conf, nil
} }

View File

@ -1,4 +1,3 @@
//go:build cgo
// +build cgo // +build cgo
/* /*
@ -26,7 +25,6 @@ import (
"crypto/sha256" "crypto/sha256"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"hash" "hash"
"net/url" "net/url"
@ -35,6 +33,7 @@ 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"
) )
@ -77,11 +76,11 @@ func rsaPublicEncryptOAEP(pubKey *rsa.PublicKey, plaintext []byte) ([]byte, stri
hashfunc = sha256.New() hashfunc = sha256.New()
hashalg = "sha256" hashalg = "sha256"
default: default:
return nil, "", fmt.Errorf("Unsupported OAEP hash '%s'", oaephash) return nil, "", errors.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, "", fmt.Errorf("rss.EncryptOAEP failed: %w", err) return nil, "", errors.Wrapf(err, "rss.EncryptOAEP failed")
} }
return ciphertext, hashalg, nil return ciphertext, hashalg, nil
@ -105,7 +104,7 @@ func pkcs11UriGetLoginParameters(p11uri *pkcs11uri.Pkcs11URI, privateKeyOperatio
module, err := p11uri.GetModule() module, err := p11uri.GetModule()
if err != nil { if err != nil {
return "", "", 0, fmt.Errorf("No module available in pkcs11 URI: %w", err) return "", "", 0, errors.Wrap(err, "No module available in pkcs11 URI")
} }
slotid := int64(-1) slotid := int64(-1)
@ -114,7 +113,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, fmt.Errorf("slot-id is not a valid number: %w", err) return "", "", 0, errors.Wrap(err, "slot-id is not a valid number")
} }
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")
@ -139,21 +138,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(slotid, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION) session, err = p11ctx.OpenSession(uint(slotid), pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
if err != nil { if err != nil {
return 0, fmt.Errorf("OpenSession to slot %d failed: %w", slotid, err) return 0, errors.Wrapf(err, "OpenSession to slot %d failed", slotid)
} }
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, fmt.Errorf("Could not login to device: %w", err) return 0, errors.Wrap(err, "Could not login to device")
} }
} }
return session, nil return session, nil
} }
// pkcs11UriLogin uses the given pkcs11 URI to select the pkcs11 module (shared library) and to get // pkcs11UriLogin uses the given pkcs11 URI to select the pkcs11 module (share libary) 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) {
@ -171,40 +170,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, fmt.Errorf("Initialize failed: %w", err) return nil, 0, errors.Wrap(err, "Initialize failed")
} }
} }
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)
slots, err := p11ctx.GetSlotList(true) if err != nil {
if err != nil { return nil, 0, errors.Wrap(err, "GetSlotList failed")
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) tokenlabel, ok := p11uri.GetPathAttribute("token", false)
if err == nil { if !ok {
return p11ctx, session, err 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")
} }
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) {
@ -234,24 +233,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, fmt.Errorf("FindObjectsInit failed: %w", err) return 0, errors.Wrap(err, "FindObjectsInit failed")
} }
obj, _, err := p11ctx.FindObjects(session, 100) obj, _, err := p11ctx.FindObjects(session, 100)
if err != nil { if err != nil {
return 0, fmt.Errorf("FindObjects failed: %w", err) return 0, errors.Wrap(err, "FindObjects failed")
} }
if err := p11ctx.FindObjectsFinal(session); err != nil { if err := p11ctx.FindObjectsFinal(session); err != nil {
return 0, fmt.Errorf("FindObjectsFinal failed: %w", err) return 0, errors.Wrap(err, "FindObjectsFinal failed")
} }
if len(obj) > 1 { if len(obj) > 1 {
return 0, fmt.Errorf("There are too many (=%d) keys with %s", len(obj), msg) return 0, errors.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, fmt.Errorf("Could not find any object with %s", msg) return 0, errors.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
@ -291,17 +290,17 @@ func publicEncryptOAEP(pubKey *Pkcs11KeyFileObject, plaintext []byte) ([]byte, s
oaep = OAEPSha256Params oaep = OAEPSha256Params
hashalg = "sha256" hashalg = "sha256"
default: default:
return nil, "", fmt.Errorf("Unsupported OAEP hash '%s'", oaephash) return nil, "", errors.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, "", fmt.Errorf("EncryptInit error: %w", err) return nil, "", errors.Wrap(err, "EncryptInit error")
} }
ciphertext, err := p11ctx.Encrypt(session, plaintext) ciphertext, err := p11ctx.Encrypt(session, plaintext)
if err != nil { if err != nil {
return nil, "", fmt.Errorf("Encrypt failed: %w", err) return nil, "", errors.Wrap(err, "Encrypt failed")
} }
return ciphertext, hashalg, nil return ciphertext, hashalg, nil
} }
@ -339,16 +338,16 @@ func privateDecryptOAEP(privKeyObj *Pkcs11KeyFileObject, ciphertext []byte, hash
case "sha256": case "sha256":
oaep = OAEPSha256Params oaep = OAEPSha256Params
default: default:
return nil, fmt.Errorf("Unsupported hash algorithm '%s' for decryption", hashalg) return nil, errors.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, fmt.Errorf("DecryptInit failed: %w", err) return nil, errors.Wrapf(err, "DecryptInit failed")
} }
plaintext, err := p11ctx.Decrypt(session, ciphertext) plaintext, err := p11ctx.Decrypt(session, ciphertext)
if err != nil { if err != nil {
return nil, fmt.Errorf("Decrypt failed: %w", err) return nil, errors.Wrapf(err, "Decrypt failed")
} }
return plaintext, err return plaintext, err
} }
@ -374,19 +373,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 (
@ -403,7 +402,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 = fmt.Errorf("Unsupported key object type for pkcs11 public key") err = errors.Errorf("Unsupported key object type for pkcs11 public key")
} }
if err != nil { if err != nil {
return nil, err return nil, err
@ -423,32 +422,33 @@ 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, fmt.Errorf("Could not parse Pkcs11Blob: %w", err) return nil, errors.Wrapf(err, "Could not parse Pkcs11Blob")
} }
switch pkcs11blob.Version { switch pkcs11blob.Version {
case 0: case 0:
// latest supported version // latest supported version
default: default:
return nil, fmt.Errorf("found Pkcs11Blob with version %d but maximum supported version is 0", pkcs11blob.Version) return nil, errors.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, fmt.Errorf("found Pkcs11Recipient with version %d but maximum supported version is 0", recipient.Version) return nil, errors.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, fmt.Errorf("Could not find a pkcs11 key for decryption:\n%s", errs) return nil, errors.Errorf("Could not find a pkcs11 key for decryption:\n%s", errs)
} }

View File

@ -1,4 +1,3 @@
//go:build !cgo
// +build !cgo // +build !cgo
/* /*
@ -19,12 +18,14 @@
package pkcs11 package pkcs11
import "fmt" import (
"github.com/pkg/errors"
)
func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) { func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
return nil, fmt.Errorf("ocicrypt pkcs11 not supported on this build") return nil, errors.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, fmt.Errorf("ocicrypt pkcs11 not supported on this build") return nil, errors.Errorf("ocicrypt pkcs11 not supported on this build")
} }

View File

@ -1,4 +1,3 @@
//go:build cgo
// +build cgo // +build cgo
/* /*

View File

@ -17,11 +17,12 @@
package pkcs11 package pkcs11
import ( import (
"fmt"
"os" "os"
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
"github.com/pkg/errors"
) )
var ( var (
@ -44,7 +45,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, fmt.Errorf("Could not set environment variable '%s' to '%s': %w", k, v, err) return nil, errors.Wrapf(err, "Could not set environment variable '%s' to '%s'", k, v)
} }
} }
@ -105,8 +106,6 @@ 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"
} }

View File

@ -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"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
) )
// 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,19 +133,16 @@ 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, fmt.Errorf("could not JSON marshal opts: %w", err) return nil, errors.Wrapf(err, "could not JSON marshal opts")
} }
pubOptsData, err = json.Marshal(opts.Public) pubOptsData, err = json.Marshal(opts.Public)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not JSON marshal opts: %w", err) return nil, errors.Wrapf(err, "could not JSON marshal opts")
} }
} }
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)
@ -214,9 +211,6 @@ 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 != "" {
@ -243,9 +237,9 @@ func decryptLayerKeyOptsData(dc *config.DecryptConfig, desc ocispec.Descriptor)
} }
} }
if !privKeyGiven { if !privKeyGiven {
return nil, fmt.Errorf("missing private key needed for decryption:\n%s", errs) return nil, errors.New("missing private key needed for decryption")
} }
return nil, fmt.Errorf("no suitable key unwrapper found or none of the private keys could be used 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)
} }
func getLayerPubOpts(desc ocispec.Descriptor) ([]byte, error) { func getLayerPubOpts(desc ocispec.Descriptor) ([]byte, error) {
@ -276,7 +270,7 @@ func preUnwrapKey(keywrapper keywrap.KeyWrapper, dc *config.DecryptConfig, b64An
} }
return optsData, nil return optsData, nil
} }
return nil, fmt.Errorf("no suitable key found for decrypting layer key:\n%s", errs) return nil, errors.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
@ -311,7 +305,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, "", fmt.Errorf("could not JSON unmarshal privOptsData: %w", err) return nil, "", errors.Wrapf(err, "could not JSON unmarshal privOptsData")
} }
lbch, err := blockcipher.NewLayerBlockCipherHandler() lbch, err := blockcipher.NewLayerBlockCipherHandler()
@ -323,7 +317,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, "", fmt.Errorf("could not JSON unmarshal pubOptsData: %w", err) return nil, "", errors.Wrapf(err, "could not JSON unmarshal pubOptsData")
} }
} }

35
go.mod
View File

@ -1,30 +1,21 @@
module github.com/containers/ocicrypt module github.com/containers/ocicrypt
go 1.22 go 1.12
toolchain go1.24.1
require ( require (
github.com/go-jose/go-jose/v4 v4.0.5 github.com/golang/protobuf v1.4.3
github.com/golang/protobuf v1.5.4 github.com/google/go-cmp v0.5.2 // indirect
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.1.0 github.com/opencontainers/image-spec v1.0.2
github.com/sirupsen/logrus v1.9.3 github.com/pkg/errors v0.9.1
github.com/smallstep/pkcs7 v0.1.1 github.com/sirupsen/logrus v1.7.0
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.10.0 github.com/stretchr/testify v1.3.0
golang.org/x/crypto v0.36.0 go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1
golang.org/x/term v0.30.0 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
google.golang.org/grpc v1.68.1 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1
gopkg.in/yaml.v3 v3.0.1 google.golang.org/grpc v1.33.2
) 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
View File

@ -1,112 +1,117 @@
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/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= 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/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
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.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
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/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M=
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
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/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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/sync v0.0.0-20220722155255-886fb9371eb4/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.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/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
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/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
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
View File

@ -17,17 +17,16 @@
package ocicrypt package ocicrypt
import ( import (
"errors"
"fmt" "fmt"
"io" "io/ioutil"
"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"
) )
@ -79,8 +78,9 @@ 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, fmt.Errorf("could not create pipe: %w", err) return nil, errors.Wrapf(err, "could not create pipe")
} }
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 := io.ReadAll(stdout) stdoutstr, err2 := ioutil.ReadAll(stdout)
stderrstr, _ := io.ReadAll(stderr) stderrstr, _ := ioutil.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,15 +310,9 @@ func resolveRecipients(gc GPGClient, recipients []string) []string {
return result return result
} }
var ( var emailPattern = regexp.MustCompile(`uid\s+\[.*\]\s.*\s<(?P<email>.+)>`)
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 ""
@ -358,7 +352,7 @@ func GPGGetPrivateKey(descs []ocispec.Descriptor, gpgClient GPGClient, gpgVault
} }
keywrapper := GetKeyWrapper(scheme) keywrapper := GetKeyWrapper(scheme)
if keywrapper == nil { if keywrapper == nil {
return nil, nil, fmt.Errorf("could not get KeyWrapper for %s", scheme) return nil, nil, errors.Errorf("could not get KeyWrapper for %s\n", scheme)
} }
keyIds, err := keywrapper.GetKeyIdsFromPacket(b64pgpPackets) keyIds, err := keywrapper.GetKeyIdsFromPacket(b64pgpPackets)
if err != nil { if err != nil {
@ -417,7 +411,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, 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, ", ")) 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, ", "))
} }
} }
} }

View File

@ -18,9 +18,9 @@ package ocicrypt
import ( import (
"bytes" "bytes"
"fmt" "io/ioutil"
"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 fmt.Errorf("could not read keyring: %w", err) return errors.Wrapf(err, "could not read keyring")
} }
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 := os.ReadFile(filename) gpgSecretKeyRingData, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,8 +1,8 @@
package helpers package helpers
import ( import (
"errors"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"strconv" "strconv"
"strings" "strings"
@ -12,6 +12,8 @@ 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
@ -41,9 +43,9 @@ func processRecipientKeys(recipients []string) ([][]byte, [][]byte, [][]byte, []
gpgRecipients = append(gpgRecipients, []byte(value)) gpgRecipients = append(gpgRecipients, []byte(value))
case "jwe": case "jwe":
tmp, err := os.ReadFile(value) tmp, err := ioutil.ReadFile(value)
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, nil, fmt.Errorf("Unable to read file: %w", err) return nil, nil, nil, nil, nil, nil, errors.Wrap(err, "Unable to read file")
} }
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")
@ -51,9 +53,9 @@ func processRecipientKeys(recipients []string) ([][]byte, [][]byte, [][]byte, []
pubkeys = append(pubkeys, tmp) pubkeys = append(pubkeys, tmp)
case "pkcs7": case "pkcs7":
tmp, err := os.ReadFile(value) tmp, err := ioutil.ReadFile(value)
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, nil, fmt.Errorf("Unable to read file: %w", err) return nil, nil, nil, nil, nil, nil, errors.Wrap(err, "Unable to read file")
} }
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")
@ -61,9 +63,9 @@ func processRecipientKeys(recipients []string) ([][]byte, [][]byte, [][]byte, []
x509s = append(x509s, tmp) x509s = append(x509s, tmp)
case "pkcs11": case "pkcs11":
tmp, err := os.ReadFile(value) tmp, err := ioutil.ReadFile(value)
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, nil, fmt.Errorf("Unable to read file: %w", err) return nil, nil, nil, nil, nil, nil, errors.Wrap(err, "Unable to read file")
} }
if encutils.IsPkcs11PublicKey(tmp) { if encutils.IsPkcs11PublicKey(tmp) {
pkcs11Yamls = append(pkcs11Yamls, tmp) pkcs11Yamls = append(pkcs11Yamls, tmp)
@ -91,9 +93,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 := os.ReadFile(fileName) tmp, err := ioutil.ReadFile(fileName)
if err != nil { if err != nil {
return nil, fmt.Errorf("Unable to read file: %w", err) return nil, errors.Wrap(err, "Unable to read file")
} }
if !encutils.IsCertificate(tmp) { if !encutils.IsCertificate(tmp) {
continue continue
@ -111,14 +113,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 os.ReadFile(pwdString[5:]) return ioutil.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, fmt.Errorf("could not parse file descriptor %s: %w", fdStr, err) return nil, errors.Wrapf(err, "could not parse file descriptor %s", fdStr)
} }
f := os.NewFile(uintptr(fd), "pwdfile") f := os.NewFile(uintptr(fd), "pwdfile")
if f == nil { if f == nil {
@ -128,7 +130,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, fmt.Errorf("could not read from file descriptor: %w", err) return nil, errors.Wrapf(err, "could not read from file descriptor")
} }
return pwd[:n], nil return pwd[:n], nil
} }
@ -172,7 +174,7 @@ func processPrivateKeyFiles(keyFilesAndPwds []string) ([][]byte, [][]byte, [][]b
} }
keyfile := parts[0] keyfile := parts[0]
tmp, err := os.ReadFile(keyfile) tmp, err := ioutil.ReadFile(keyfile)
if err != nil { if err != nil {
return nil, nil, nil, nil, nil, nil, err return nil, nil, nil, nil, nil, nil, err
} }
@ -372,6 +374,7 @@ 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
} }

View File

@ -18,13 +18,12 @@ 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/go-jose/go-jose/v4" "github.com/pkg/errors"
jose "gopkg.in/square/go-jose.v2"
) )
type jweKeyWrapper struct { type jweKeyWrapper struct {
@ -55,21 +54,17 @@ 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, fmt.Errorf("jose.NewMultiEncrypter failed: %w", err) return nil, errors.Wrapf(err, "jose.NewMultiEncrypter failed")
} }
jwe, err := encrypter.Encrypt(optsData) jwe, err := encrypter.Encrypt(optsData)
if err != nil { if err != nil {
return nil, fmt.Errorf("JWE Encrypt failed: %w", err) return nil, errors.Wrapf(err, "JWE Encrypt failed")
} }
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) {
// cf. list of algorithms in func addPubKeys() below jwe, err := jose.ParseEncrypted(string(jweString))
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")
} }
@ -127,24 +122,9 @@ func addPubKeys(joseRecipients *[]jose.Recipient, pubKeys [][]byte) error {
} }
alg := jose.RSA_OAEP alg := jose.RSA_OAEP
switch key := key.(type) { switch 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{

View File

@ -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"
"github.com/go-jose/go-jose/v4" jose "gopkg.in/square/go-jose.v2"
) )
var oneEmpty []byte var oneEmpty []byte
@ -70,21 +70,6 @@ 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
{ {
@ -241,27 +226,6 @@ 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
} }

View File

@ -19,14 +19,12 @@ 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"
) )
@ -114,18 +112,19 @@ 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, fmt.Errorf("error while retrieving keyprovider protocol command output: %w", err) return nil, errors.Wrap(err, "error while retrieving keyprovider protocol command output")
} }
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, fmt.Errorf("error while retrieving keyprovider protocol grpc output: %w", err) return nil, errors.Wrap(err, "error while retrieving keyprovider protocol grpc output")
} }
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
@ -161,8 +160,9 @@ 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, fmt.Errorf("error while dialing rpc server: %w", err) return nil, errors.Wrap(err, "error while dialing rpc server")
} }
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, fmt.Errorf("Error from grpc method: %w", err) return nil, errors.Wrap(err, "Error from grpc method")
} }
} 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, fmt.Errorf("Error from grpc method: %w", err) return nil, errors.Wrap(err, "Error from grpc method")
} }
} 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, fmt.Errorf("Error while unmarshalling grpc method output: %w", err) return nil, errors.Wrap(err, "Error while unmarshalling grpc method output")
} }
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, fmt.Errorf("Error while unmarshalling binary executable command output: %w", err) return nil, errors.Wrap(err, "Error while unmarshalling binary executable command output")
} }
return &protocolOuput, nil return &protocolOuput, nil
} }

View File

@ -24,29 +24,28 @@ 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"
) )
// TestRunner mocks binary executable for key wrapping and unwrapping //Test runner which 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
} }
@ -69,14 +68,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
} }
@ -101,12 +100,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
@ -134,7 +133,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)
@ -142,7 +141,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)
@ -161,12 +160,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
@ -184,7 +183,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("unknown protocol") return nil, errors.New("unkown protocol")
} }
func TestKeyWrapKeyProviderCommandSuccess(t *testing.T) { func TestKeyWrapKeyProviderCommandSuccess(t *testing.T) {
@ -365,6 +364,7 @@ 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,3 +376,5 @@ func TestKeyWrapKeyProviderGRPCSuccess(t *testing.T) {
assert.Equal(t, optsData, keyUnWrapOutput) assert.Equal(t, optsData, keyUnWrapOutput)
os.Remove(path) os.Remove(path)
} }

View File

@ -21,15 +21,16 @@ 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"
) )
@ -63,7 +64,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, fmt.Errorf("unable to create entity list: %w", err) return nil, errors.Wrap(err, "unable to create entity list")
} }
if len(el) == 0 { if len(el) == 0 {
// nothing to do -- not an error // nothing to do -- not an error
@ -99,7 +100,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, fmt.Errorf("unable to parse private keys: %w", err) return nil, errors.Wrap(err, "unable to parse private keys")
} }
var prompt openpgp.PromptFunction var prompt openpgp.PromptFunction
@ -125,7 +126,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 := io.ReadAll(md.UnverifiedBody) optsData, err := ioutil.ReadAll(md.UnverifiedBody)
if err != nil { if err != nil {
continue continue
} }
@ -141,7 +142,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, fmt.Errorf("could not decode base64 encoded PGP packet: %w", err) return nil, errors.Wrapf(err, "could not decode base64 encoded PGP packet")
} }
newids, err := kw.getKeyIDs(pgpPacket) newids, err := kw.getKeyIDs(pgpPacket)
if err != nil { if err != nil {
@ -165,7 +166,7 @@ ParsePackets:
break ParsePackets break ParsePackets
} }
if err != nil { if err != nil {
return []uint64{}, fmt.Errorf("packets.Next() failed: %w", err) return []uint64{}, errors.Wrapf(err, "packets.Next() failed")
} }
switch p := p.(type) { switch p := p.(type) {
case *packet.EncryptedKey: case *packet.EncryptedKey:

View File

@ -17,13 +17,12 @@
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 {
@ -41,11 +40,7 @@ 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) {
// append({}, ...) allocates a fresh backing array, and that's necessary to guarantee concurrent calls to WrapKeys (as in c/image/copy.Image) pkcs11Recipients, err := addPubKeys(&ec.DecryptConfig, append(ec.Parameters["pkcs11-pubkeys"], ec.Parameters["pkcs11-yamls"]...))
// 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
} }
@ -56,7 +51,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, fmt.Errorf("PKCS11 EncryptMulitple failed: %w", err) return nil, errors.Wrapf(err, "PKCS11 EncryptMulitple failed")
} }
return jsonString, nil return jsonString, nil
} }
@ -96,7 +91,7 @@ func (kw *pkcs11KeyWrapper) UnwrapKey(dc *config.DecryptConfig, jsonString []byt
return plaintext, nil return plaintext, nil
} }
return nil, fmt.Errorf("PKCS11: No suitable private key found for decryption: %w", err) return nil, errors.Wrapf(err, "PKCS11: No suitable private key found for decryption")
} }
func (kw *pkcs11KeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool { func (kw *pkcs11KeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool {
@ -144,7 +139,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])
} }

View File

@ -22,8 +22,8 @@ import (
"testing" "testing"
"github.com/containers/ocicrypt/config" "github.com/containers/ocicrypt/config"
"github.com/containers/ocicrypt/crypto/pkcs11"
"github.com/containers/ocicrypt/utils" "github.com/containers/ocicrypt/utils"
"github.com/containers/ocicrypt/crypto/pkcs11"
"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": {pubKey2Pem}, "pkcs11-pubkeys": {[]byte(pubKey2Pem)},
}, },
DecryptConfig: config.DecryptConfig{ DecryptConfig: config.DecryptConfig{
Parameters: map[string][][]byte{ Parameters: map[string][][]byte{

View File

@ -19,13 +19,12 @@ 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/smallstep/pkcs7" "github.com/pkg/errors"
"go.mozilla.org/pkcs7"
) )
type pkcs7KeyWrapper struct { type pkcs7KeyWrapper struct {
@ -105,7 +104,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, fmt.Errorf("could not parse PKCS7 packet: %w", err) return nil, errors.Wrapf(err, "could not parse PKCS7 packet")
} }
for idx, privKey := range privKeys { for idx, privKey := range privKeys {

View File

@ -3,18 +3,10 @@ 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 gzip-compressed layers. // MediaTypeLayerGzipEnc is MIME type used for encrypted 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"
// MediaTypeLayerNonDistributableGzipEnc is MIME type used for non distributable encrypted gzip-compressed layers. // MediaTypeLayerGzipEnc is MIME type used for non distributable encrypted 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
) )

View File

@ -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,15 +44,13 @@ 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, fmt.Errorf("Error while running command: %s. stderr: %s: %w", cmdName, stderr.String(), err) return nil, errors.Wrapf(err, "Error while running command: %s", cmdName)
} }
return out.Bytes(), nil return out.Bytes(), nil
} }

View File

@ -18,11 +18,12 @@ package softhsm
import ( import (
"bytes" "bytes"
"errors" "io/ioutil"
"fmt"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
"github.com/pkg/errors"
) )
type SoftHSMSetup struct { type SoftHSMSetup struct {
@ -41,9 +42,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 := os.MkdirTemp("", "ocicrypt") statedir, err := ioutil.TempDir("", "ocicrypt")
if err != nil { if err != nil {
return "", fmt.Errorf("Could not create temporary directory fot softhsm state: %w", err) return "", errors.Wrapf(err, "Could not create temporary directory fot softhsm state")
} }
s.statedir = statedir s.statedir = statedir
@ -54,7 +55,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 "", fmt.Errorf("%s setup failed: %s: %w", softhsmSetup, out.String(), err) return "", errors.Wrapf(err, "%s setup failed: %s", softhsmSetup, out.String())
} }
o := out.String() o := out.String()
@ -75,7 +76,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 "", fmt.Errorf("%s getpubkey failed: %s: %w", softhsmSetup, out.String(), err) return "", errors.Wrapf(err, "%s getpubkey failed: %s", softhsmSetup, out.String())
} }
return out.String(), nil return out.String(), nil

View File

@ -24,25 +24,17 @@ 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, fmt.Errorf("rsa.GenerateKey failed: %w", err) return nil, errors.Wrap(err, "rsa.GenerateKey failed")
}
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
} }
@ -57,7 +49,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, fmt.Errorf("x509.MarshalPKIXPublicKey failed: %w", err) return nil, nil, errors.Wrap(err, "x509.MarshalPKIXPublicKey failed")
} }
privData := x509.MarshalPKCS1PrivateKey(key) privData := x509.MarshalPKCS1PrivateKey(key)
@ -77,7 +69,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, fmt.Errorf("x509.EncryptPEMBlock failed: %w", err) return nil, nil, errors.Wrap(err, "x509.EncryptPEMBlock failed")
} }
} else { } else {
block = &pem.Block{ block = &pem.Block{
@ -94,19 +86,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 := CreateECDSAKey(curve) key, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, errors.Wrapf(err, "ecdsa.GenerateKey failed")
} }
pubData, err := x509.MarshalPKIXPublicKey(&key.PublicKey) pubData, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("x509.MarshalPKIXPublicKey failed: %w", err) return nil, nil, errors.Wrapf(err, "x509.MarshalPKIXPublicKey failed")
} }
privData, err := x509.MarshalECPrivateKey(key) privData, err := x509.MarshalECPrivateKey(key)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("x509.MarshalECPrivateKey failed: %w", err) return nil, nil, errors.Wrapf(err, "x509.MarshalECPrivateKey failed")
} }
return pubData, privData, nil return pubData, privData, nil
@ -116,7 +108,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, fmt.Errorf("rsa.GenerateKey failed: %w", err) return nil, nil, errors.Wrap(err, "rsa.GenerateKey failed")
} }
ca := &x509.Certificate{ ca := &x509.Certificate{
@ -162,12 +154,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, fmt.Errorf("x509.CreateCertificate failed: %w", err) return nil, errors.Wrap(err, "x509.CreateCertificate failed")
} }
cert, err := x509.ParseCertificate(certDER) cert, err := x509.ParseCertificate(certDER)
if err != nil { if err != nil {
return nil, fmt.Errorf("x509.ParseCertificate failed: %w", err) return nil, errors.Wrap(err, "x509.ParseCertificate failed")
} }
return cert, nil return cert, nil

View File

@ -21,21 +21,22 @@ 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 := jose.JSONWebKey{} jwk := json.JSONWebKey{}
err := jwk.UnmarshalJSON(privKey) err := jwk.UnmarshalJSON(privKey)
if err != nil { if err != nil {
return nil, fmt.Errorf("%s: Could not parse input as JWK: %w", prefix, err) return nil, errors.Wrapf(err, "%s: Could not parse input as JWK", prefix)
} }
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)
@ -45,10 +46,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 := jose.JSONWebKey{} jwk := json.JSONWebKey{}
err := jwk.UnmarshalJSON(privKey) err := jwk.UnmarshalJSON(privKey)
if err != nil { if err != nil {
return nil, fmt.Errorf("%s: Could not parse input as JWK: %w", prefix, err) return nil, errors.Wrapf(err, "%s: Could not parse input as JWK", prefix)
} }
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)
@ -96,11 +97,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, fmt.Errorf("%s: Missing password for encrypted private key", prefix) return nil, errors.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, fmt.Errorf("%s: Wrong password: could not decrypt private key", prefix) return nil, errors.Errorf("%s: Wrong password: could not decrypt private key", prefix)
} }
} else { } else {
der = block.Bytes der = block.Bytes
@ -110,7 +111,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, fmt.Errorf("%s: Could not parse private key: %w", prefix, err) return nil, errors.Wrapf(err, "%s: Could not parse private key", prefix)
} }
} }
} else { } else {
@ -144,7 +145,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, fmt.Errorf("%s: Could not parse public key: %w", prefix, err) return nil, errors.Wrapf(err, "%s: Could not parse public key", prefix)
} }
} else { } else {
key, err = parseJWKPublicKey(pubKey, prefix) key, err = parseJWKPublicKey(pubKey, prefix)
@ -178,7 +179,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, fmt.Errorf("%s: Could not parse x509 certificate: %w", prefix, err) return nil, errors.Wrapf(err, "%s: Could not parse x509 certificate", prefix)
} }
} }
return x509Cert, err return x509Cert, err