Update to newest imgcrypt, aufs and zfs

Older versions transitively dragged in k8s.io/kubernetes, the newer
versions do not.

Signed-off-by: Davanum Srinivas <davanum@gmail.com>
This commit is contained in:
Davanum Srinivas
2021-03-01 10:36:12 -05:00
parent 54a63a3dd6
commit c3eecf4f75
274 changed files with 16327 additions and 3236 deletions

28
vendor/github.com/containers/ocicrypt/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,28 @@
dist: bionic
language: go
os:
- linux
go:
- "1.13.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

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: check build decoder
.PHONY: check build decoder generate-protobuf
all: build
@@ -28,4 +28,7 @@ vendor:
go mod tidy
test:
go test ./...
go test ./... -test.v
generate-protobuf:
protoc -I utils/keyprovider/ utils/keyprovider/keyprovider.proto --go_out=plugins=grpc:utils/keyprovider

View File

@@ -2,9 +2,16 @@
The `ocicrypt` library is the OCI image spec implementation of container image encryption. More details of the spec can be seen in the [OCI repository](https://github.com/opencontainers/image-spec/pull/775). The purpose of this library is to encode spec structures and consts in code, as well as provide a consistent implementation of image encryption across container runtimes and build tools.
Consumers of OCIcrypt:
- [containerd/imgcrypt](https://github.com/containerd/imgcrypt)
- [cri-o](https://github.com/cri-o/cri-o)
- [skopeo](https://github.com/containers/skopeo)
## Usage
There are various levels of usage for this library. The main consumers of these would be runtime/buil tools, and a more specific use would be in the ability to extend cryptographic function.
There are various levels of usage for this library. The main consumers of these would be runtime/build tools, and a more specific use would be in the ability to extend cryptographic function.
### Runtime/Build tool usage
@@ -16,12 +23,12 @@ func EncryptLayer(ec *config.EncryptConfig, encOrPlainLayerReader io.Reader, des
func DecryptLayer(dc *config.DecryptConfig, encLayerReader io.Reader, desc ocispec.Descriptor, unwrapOnly bool) (io.Reader, digest.Digest, error)
```
The settings/parameters to these functions can be specified via creation of an encryption config with the `github.com/containers/ocicrypt/config` package. We note that because setting of annotations and other fields of the layer descriptor is done through various means in different runtimes/build tools, it is the resposibility of the caller to still ensure that the layer descriptor follows the OCI specification (i.e. encoding, setting annotations, etc.).
The settings/parameters to these functions can be specified via creation of an encryption config with the `github.com/containers/ocicrypt/config` package. We note that because setting of annotations and other fields of the layer descriptor is done through various means in different runtimes/build tools, it is the responsibility of the caller to still ensure that the layer descriptor follows the OCI specification (i.e. encoding, setting annotations, etc.).
### Crypto Agility and Extensibility
The implementation for both symmetric and assymetric encryption used in this library are behind 2 main interfaces, which users can extend if need be. These are in the following packages:
The implementation for both symmetric and asymmetric encryption used in this library are behind 2 main interfaces, which users can extend if need be. These are in the following packages:
- github.com/containers/ocicrypt/blockcipher - LayerBlockCipher interface for block ciphers
- github.com/containers/ocicrypt/keywrap - KeyWrapper interface for key wrapping
@@ -30,3 +37,8 @@ We note that adding interfaces here is risky outside the OCI spec is not recomme
## Security Issues
We consider security issues related to this library critical. Please report and security related issues by emailing maintainers in the [MAINTAINERS](MAINTAINERS) file.
## Ocicrypt Pkcs11 Support
Ocicrypt Pkcs11 support is currently experiemental. For more details, please refer to the [this document](docs/pkcs11.md).

3
vendor/github.com/containers/ocicrypt/SECURITY.md generated vendored Normal file
View File

@@ -0,0 +1,3 @@
## Security and Disclosure Information Policy for the OCIcrypt Library Project
The OCIcrypt Library Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/master/SECURITY.md) for the Containers Projects.

View File

@@ -17,7 +17,11 @@
package config
import (
"github.com/containers/ocicrypt/crypto/pkcs11"
"strings"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
)
// EncryptWithJwe returns a CryptoConfig to encrypt with jwe public keys
@@ -70,6 +74,88 @@ func EncryptWithGpg(gpgRecipients [][]byte, gpgPubRingFile []byte) (CryptoConfig
}, nil
}
// EncryptWithPkcs11 returns a CryptoConfig to encrypt with configured pkcs11 parameters
func EncryptWithPkcs11(pkcs11Config *pkcs11.Pkcs11Config, pkcs11Pubkeys, pkcs11Yamls [][]byte) (CryptoConfig, error) {
dc := DecryptConfig{}
ep := map[string][][]byte{}
if len(pkcs11Yamls) > 0 {
if pkcs11Config == nil {
return CryptoConfig{}, errors.New("pkcs11Config must not be nil")
}
p11confYaml, err := yaml.Marshal(pkcs11Config)
if err != nil {
return CryptoConfig{}, errors.Wrapf(err, "Could not marshal Pkcs11Config to Yaml")
}
dc = DecryptConfig{
Parameters: map[string][][]byte{
"pkcs11-config": {p11confYaml},
},
}
ep["pkcs11-yamls"] = pkcs11Yamls
}
if len(pkcs11Pubkeys) > 0 {
ep["pkcs11-pubkeys"] = pkcs11Pubkeys
}
return CryptoConfig{
EncryptConfig: &EncryptConfig{
Parameters: ep,
DecryptConfig: dc,
},
DecryptConfig: &dc,
}, nil
}
// EncryptWithKeyProvider returns a CryptoConfig to encrypt with configured keyprovider parameters
func EncryptWithKeyProvider(keyProviders [][]byte) (CryptoConfig, error) {
dc := DecryptConfig{}
ep := make(map[string][][]byte)
for _, keyProvider := range keyProviders {
keyProvidersStr := string(keyProvider)
idx := strings.Index(keyProvidersStr, ":")
if idx > 0 {
ep[keyProvidersStr[:idx]] = append(ep[keyProvidersStr[:idx]], []byte(keyProvidersStr[idx+1:]))
} else {
ep[keyProvidersStr] = append(ep[keyProvidersStr], []byte("Enabled"))
}
}
return CryptoConfig{
EncryptConfig: &EncryptConfig{
Parameters: ep,
DecryptConfig: dc,
},
DecryptConfig: &dc,
}, nil
}
// DecryptWithKeyProvider returns a CryptoConfig to decrypt with configured keyprovider parameters
func DecryptWithKeyProvider(keyProviders [][]byte) (CryptoConfig, error) {
dp := make(map[string][][]byte)
ep := map[string][][]byte{}
for _, keyProvider := range keyProviders {
keyProvidersStr := string(keyProvider)
idx := strings.Index(keyProvidersStr, ":")
if idx > 0 {
dp[keyProvidersStr[:idx]] = append(dp[keyProvidersStr[:idx]], []byte(keyProvidersStr[idx+1:]))
} else {
dp[keyProvidersStr] = append(dp[keyProvidersStr], []byte("Enabled"))
}
}
dc := DecryptConfig{
Parameters: dp,
}
return CryptoConfig{
EncryptConfig: &EncryptConfig{
Parameters: ep,
DecryptConfig: dc,
},
DecryptConfig: &dc,
}, nil
}
// DecryptWithPrivKeys returns a CryptoConfig to decrypt with configured private keys
func DecryptWithPrivKeys(privKeys [][]byte, privKeysPasswords [][]byte) (CryptoConfig, error) {
if len(privKeys) != len(privKeysPasswords) {
@@ -132,3 +218,28 @@ func DecryptWithGpgPrivKeys(gpgPrivKeys, gpgPrivKeysPwds [][]byte) (CryptoConfig
DecryptConfig: &dc,
}, nil
}
// DecryptWithPkcs11Yaml returns a CryptoConfig to decrypt with pkcs11 YAML formatted key files
func DecryptWithPkcs11Yaml(pkcs11Config *pkcs11.Pkcs11Config, pkcs11Yamls [][]byte) (CryptoConfig, error) {
p11confYaml, err := yaml.Marshal(pkcs11Config)
if err != nil {
return CryptoConfig{}, errors.Wrapf(err, "Could not marshal Pkcs11Config to Yaml")
}
dc := DecryptConfig{
Parameters: map[string][][]byte{
"pkcs11-yamls": pkcs11Yamls,
"pkcs11-config": {p11confYaml},
},
}
ep := map[string][][]byte{}
return CryptoConfig{
EncryptConfig: &EncryptConfig{
Parameters: ep,
DecryptConfig: dc,
},
DecryptConfig: &dc,
}, nil
}

View File

@@ -0,0 +1,81 @@
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import (
"encoding/json"
"github.com/pkg/errors"
"io/ioutil"
"os"
)
// Command describes the structure of command, it consist of path and args, where path defines the location of
// binary executable and args are passed on to the binary executable
type Command struct {
Path string `json:"path,omitempty"`
Args []string `json:"args,omitempty"`
}
// KeyProviderAttrs describes the structure of key provider, it defines the way of invocation to key provider
type KeyProviderAttrs struct {
Command *Command `json:"cmd,omitempty"`
Grpc string `json:"grpc,omitempty"`
}
// OcicryptConfig represents the format of an ocicrypt_provider.conf config file
type OcicryptConfig struct {
KeyProviderConfig map[string]KeyProviderAttrs `json:"key-providers"`
}
const ENVVARNAME = "OCICRYPT_KEYPROVIDER_CONFIG"
// parseConfigFile parses a configuration file; it is not an error if the configuration file does
// not exist, so no error is returned.
func parseConfigFile(filename string) (*OcicryptConfig, error) {
// a non-existent config file is not an error
_, err := os.Stat(filename)
if os.IsNotExist(err) {
return nil, nil
}
data, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
ic := &OcicryptConfig{}
err = json.Unmarshal(data, ic)
return ic, err
}
// getConfiguration tries to read the configuration file at the following locations
// ${OCICRYPT_KEYPROVIDER_CONFIG} == "/etc/ocicrypt_keyprovider.yaml"
// If no configuration file could be found or read a null pointer is returned
func GetConfiguration() (*OcicryptConfig, error) {
var ic *OcicryptConfig
var err error
filename := os.Getenv(ENVVARNAME)
if len(filename) > 0 {
ic, err = parseConfigFile(filename)
if err != nil {
return nil, errors.Wrap(err, "Error while parsing keyprovider config file")
}
} else {
return nil, nil
}
return ic, nil
}

View File

@@ -0,0 +1,134 @@
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pkcs11
import (
"fmt"
"github.com/pkg/errors"
pkcs11uri "github.com/stefanberger/go-pkcs11uri"
"gopkg.in/yaml.v2"
)
// Pkcs11KeyFile describes the format of the pkcs11 (private) key file.
// It also carries pkcs11 module related environment variables that are transferred to the
// Pkcs11URI object and activated when the pkcs11 module is used.
type Pkcs11KeyFile struct {
Pkcs11 struct {
Uri string `yaml:"uri"`
} `yaml:"pkcs11"`
Module struct {
Env map[string]string `yaml:"env,omitempty"`
} `yaml:"module"`
}
// Pkcs11KeyFileObject is a representation of the Pkcs11KeyFile with the pkcs11 URI as an object
type Pkcs11KeyFileObject struct {
Uri *pkcs11uri.Pkcs11URI
}
// ParsePkcs11Uri parses a pkcs11 URI
func ParsePkcs11Uri(uri string) (*pkcs11uri.Pkcs11URI, error) {
p11uri := pkcs11uri.New()
err := p11uri.Parse(uri)
if err != nil {
return nil, errors.Wrapf(err, "Could not parse Pkcs11URI from file")
}
return p11uri, err
}
// ParsePkcs11KeyFile parses a pkcs11 key file holding a pkcs11 URI describing a private key.
// The file has the following yaml format:
// pkcs11:
// - uri : <pkcs11 uri>
// An error is returned if the pkcs11 URI is malformed
func ParsePkcs11KeyFile(yamlstr []byte) (*Pkcs11KeyFileObject, error) {
p11keyfile := Pkcs11KeyFile{}
err := yaml.Unmarshal([]byte(yamlstr), &p11keyfile)
if err != nil {
return nil, errors.Wrapf(err, "Could not unmarshal pkcs11 keyfile")
}
p11uri, err := ParsePkcs11Uri(p11keyfile.Pkcs11.Uri)
if err != nil {
return nil, err
}
p11uri.SetEnvMap(p11keyfile.Module.Env)
return &Pkcs11KeyFileObject{Uri: p11uri}, err
}
// IsPkcs11PrivateKey checks whether the given YAML represents a Pkcs11 private key
func IsPkcs11PrivateKey(yamlstr []byte) bool {
_, err := ParsePkcs11KeyFile(yamlstr)
return err == nil
}
// IsPkcs11PublicKey checks whether the given YAML represents a Pkcs11 public key
func IsPkcs11PublicKey(yamlstr []byte) bool {
_, err := ParsePkcs11KeyFile(yamlstr)
return err == nil
}
// Pkcs11Config describes the layout of a pkcs11 config file
// The file has the following yaml format:
// module-directories:
// - /usr/lib64/pkcs11/
// allowd-module-paths
// - /usr/lib64/pkcs11/libsofthsm2.so
type Pkcs11Config struct {
ModuleDirectories []string `yaml:"module-directories"`
AllowedModulePaths []string `yaml:"allowed-module-paths"`
}
// GetDefaultModuleDirectories returns module directories covering
// a variety of Linux distros
func GetDefaultModuleDirectories() []string {
dirs := []string{
"/usr/lib64/pkcs11/", // Fedora,RHEL,openSUSE
"/usr/lib/pkcs11/", // Fedora,ArchLinux
"/usr/local/lib/pkcs11/",
"/usr/lib/softhsm/", // Debian,Ubuntu
}
// Debian directory: /usr/lib/(x86_64|aarch64|arm|powerpc64le|s390x)-linux-gnu/
hosttype, ostype, q := getHostAndOsType()
if len(hosttype) > 0 {
dir := fmt.Sprintf("/usr/lib/%s-%s-%s/", hosttype, ostype, q)
dirs = append(dirs, dir)
}
return dirs
}
// GetDefaultModuleDirectoresFormatted returns the default module directories formatted for YAML
func GetDefaultModuleDirectoriesYaml(indent string) string {
res := ""
for _, dir := range GetDefaultModuleDirectories() {
res += indent + "- " + dir + "\n"
}
return res
}
// ParsePkcs11ConfigFile parses a pkcs11 config file hat influences the module search behavior
// as well as the set of modules that users are allowed to use
func ParsePkcs11ConfigFile(yamlstr []byte) (*Pkcs11Config, error) {
p11conf := Pkcs11Config{}
err := yaml.Unmarshal([]byte(yamlstr), &p11conf)
if err != nil {
return &p11conf, errors.Wrapf(err, "Could not parse Pkcs11Config")
}
return &p11conf, nil
}

View File

@@ -0,0 +1,487 @@
// +build cgo
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pkcs11
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"hash"
"net/url"
"os"
"strconv"
"strings"
"github.com/miekg/pkcs11"
"github.com/pkg/errors"
pkcs11uri "github.com/stefanberger/go-pkcs11uri"
)
var (
// OAEPLabel defines the label we use for OAEP encryption; this cannot be changed
OAEPLabel = []byte("")
// OAEPDefaultHash defines the default hash used for OAEP encryption; this cannot be changed
OAEPDefaultHash = "sha1"
// OAEPSha1Params describes the OAEP parameters with sha1 hash algorithm; needed by SoftHSM
OAEPSha1Params = &pkcs11.OAEPParams{
HashAlg: pkcs11.CKM_SHA_1,
MGF: pkcs11.CKG_MGF1_SHA1,
SourceType: pkcs11.CKZ_DATA_SPECIFIED,
SourceData: OAEPLabel,
}
// OAEPSha256Params describes the OAEP parameters with sha256 hash algorithm
OAEPSha256Params = &pkcs11.OAEPParams{
HashAlg: pkcs11.CKM_SHA256,
MGF: pkcs11.CKG_MGF1_SHA256,
SourceType: pkcs11.CKZ_DATA_SPECIFIED,
SourceData: OAEPLabel,
}
)
// rsaPublicEncryptOAEP encrypts the given plaintext with the given *rsa.PublicKey; the
// environment variable OCICRYPT_OAEP_HASHALG can be set to 'sha1' to force usage of sha1 for OAEP (SoftHSM).
// This function is needed by clients who are using a public key file for pkcs11 encryption
func rsaPublicEncryptOAEP(pubKey *rsa.PublicKey, plaintext []byte) ([]byte, string, error) {
var (
hashfunc hash.Hash
hashalg string
)
oaephash := os.Getenv("OCICRYPT_OAEP_HASHALG")
// The default is 'sha1'
switch strings.ToLower(oaephash) {
case "sha1", "":
hashfunc = sha1.New()
hashalg = "sha1"
case "sha256":
hashfunc = sha256.New()
hashalg = "sha256"
default:
return nil, "", errors.Errorf("Unsupported OAEP hash '%s'", oaephash)
}
ciphertext, err := rsa.EncryptOAEP(hashfunc, rand.Reader, pubKey, plaintext, OAEPLabel)
if err != nil {
return nil, "", errors.Wrapf(err, "rss.EncryptOAEP failed")
}
return ciphertext, hashalg, nil
}
// pkcs11UriGetLoginParameters gets the parameters necessary for login from the Pkcs11URI
// PIN and module are mandatory; slot-id is optional and if not found -1 will be returned
// For a privateKeyOperation a PIN is required and if none is given, this function will return an error
func pkcs11UriGetLoginParameters(p11uri *pkcs11uri.Pkcs11URI, privateKeyOperation bool) (string, string, int64, error) {
var (
pin string
err error
)
if privateKeyOperation {
if !p11uri.HasPIN() {
return "", "", 0, errors.New("Missing PIN for private key operation")
}
}
// some devices require a PIN to find a *public* key object, others don't
pin, _ = p11uri.GetPIN()
module, err := p11uri.GetModule()
if err != nil {
return "", "", 0, errors.Wrap(err, "No module available in pkcs11 URI")
}
slotid := int64(-1)
slot, ok := p11uri.GetPathAttribute("slot-id", false)
if ok {
slotid, err = strconv.ParseInt(slot, 10, 64)
if err != nil {
return "", "", 0, errors.Wrap(err, "slot-id is not a valid number")
}
if slotid < 0 {
return "", "", 0, fmt.Errorf("slot-id is a negative number")
}
if uint64(slotid) > 0xffffffff {
return "", "", 0, fmt.Errorf("slot-id is larger than 32 bit")
}
}
return pin, module, slotid, nil
}
// pkcs11UriGetKeyIdAndLabel gets the key label by retrieving the value of the 'object' attribute
func pkcs11UriGetKeyIdAndLabel(p11uri *pkcs11uri.Pkcs11URI) (string, string, error) {
keyid, ok2 := p11uri.GetPathAttribute("id", false)
label, ok1 := p11uri.GetPathAttribute("object", false)
if !ok1 && !ok2 {
return "", "", errors.New("Neither 'id' nor 'object' attributes were found in pkcs11 URI")
}
return keyid, label, nil
}
// pkcs11OpenSession opens a session with a pkcs11 device at the given slot and logs in with the given PIN
func pkcs11OpenSession(p11ctx *pkcs11.Ctx, slotid uint, pin string) (session pkcs11.SessionHandle, err error) {
session, err = p11ctx.OpenSession(uint(slotid), pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
if err != nil {
return 0, errors.Wrapf(err, "OpenSession to slot %d failed", slotid)
}
if len(pin) > 0 {
err = p11ctx.Login(session, pkcs11.CKU_USER, pin)
if err != nil {
_ = p11ctx.CloseSession(session)
return 0, errors.Wrap(err, "Could not login to device")
}
}
return session, nil
}
// 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
// one slot after the other will be attempted and the first one where login succeeds will be used
func pkcs11UriLogin(p11uri *pkcs11uri.Pkcs11URI, privateKeyOperation bool) (ctx *pkcs11.Ctx, session pkcs11.SessionHandle, err error) {
pin, module, slotid, err := pkcs11UriGetLoginParameters(p11uri, privateKeyOperation)
if err != nil {
return nil, 0, err
}
p11ctx := pkcs11.New(module)
if p11ctx == nil {
return nil, 0, errors.New("Please check module path, input is: " + module)
}
err = p11ctx.Initialize()
if err != nil {
p11Err := err.(pkcs11.Error)
if p11Err != pkcs11.CKR_CRYPTOKI_ALREADY_INITIALIZED {
return nil, 0, errors.Wrap(err, "Initialize failed")
}
}
if slotid >= 0 {
session, err := pkcs11OpenSession(p11ctx, uint(slotid), pin)
return p11ctx, session, err
} else {
slots, err := p11ctx.GetSlotList(true)
if err != nil {
return nil, 0, errors.Wrap(err, "GetSlotList failed")
}
tokenlabel, ok := p11uri.GetPathAttribute("token", false)
if !ok {
return nil, 0, errors.New("Missing 'token' attribute since 'slot-id' was not given")
}
for _, slot := range slots {
ti, err := p11ctx.GetTokenInfo(slot)
if err != nil || ti.Label != tokenlabel {
continue
}
session, err = pkcs11OpenSession(p11ctx, slot, pin)
if err == nil {
return p11ctx, session, err
}
}
if len(pin) > 0 {
return nil, 0, errors.New("Could not create session to any slot and/or log in")
}
return nil, 0, errors.New("Could not create session to any slot")
}
}
func pkcs11Logout(ctx *pkcs11.Ctx, session pkcs11.SessionHandle) {
_ = ctx.Logout(session)
_ = ctx.CloseSession(session)
_ = ctx.Finalize()
ctx.Destroy()
}
// findObject finds an object of the given class with the given keyid and/or label
func findObject(p11ctx *pkcs11.Ctx, session pkcs11.SessionHandle, class uint, keyid, label string) (pkcs11.ObjectHandle, error) {
msg := ""
template := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, class),
}
if len(label) > 0 {
template = append(template, pkcs11.NewAttribute(pkcs11.CKA_LABEL, label))
msg = fmt.Sprintf("label '%s'", label)
}
if len(keyid) > 0 {
template = append(template, pkcs11.NewAttribute(pkcs11.CKA_ID, keyid))
if len(msg) > 0 {
msg += " and "
}
msg += url.PathEscape(keyid)
}
if err := p11ctx.FindObjectsInit(session, template); err != nil {
return 0, errors.Wrap(err, "FindObjectsInit failed")
}
obj, _, err := p11ctx.FindObjects(session, 100)
if err != nil {
return 0, errors.Wrap(err, "FindObjects failed")
}
if err := p11ctx.FindObjectsFinal(session); err != nil {
return 0, errors.Wrap(err, "FindObjectsFinal failed")
}
if len(obj) > 1 {
return 0, errors.Errorf("There are too many (=%d) keys with %s", len(obj), msg)
} else if len(obj) == 1 {
return obj[0], nil
}
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
func publicEncryptOAEP(pubKey *Pkcs11KeyFileObject, plaintext []byte) ([]byte, string, error) {
oldenv, err := setEnvVars(pubKey.Uri.GetEnvMap())
if err != nil {
return nil, "", err
}
defer restoreEnv(oldenv)
p11ctx, session, err := pkcs11UriLogin(pubKey.Uri, false)
if err != nil {
return nil, "", err
}
defer pkcs11Logout(p11ctx, session)
keyid, label, err := pkcs11UriGetKeyIdAndLabel(pubKey.Uri)
if err != nil {
return nil, "", err
}
p11PubKey, err := findObject(p11ctx, session, pkcs11.CKO_PUBLIC_KEY, keyid, label)
if err != nil {
return nil, "", err
}
var hashalg string
var oaep *pkcs11.OAEPParams
oaephash := os.Getenv("OCICRYPT_OAEP_HASHALG")
// the default is sha1
switch strings.ToLower(oaephash) {
case "sha1", "":
oaep = OAEPSha1Params
hashalg = "sha1"
case "sha256":
oaep = OAEPSha256Params
hashalg = "sha256"
default:
return nil, "", errors.Errorf("Unsupported OAEP hash '%s'", oaephash)
}
err = p11ctx.EncryptInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_OAEP, oaep)}, p11PubKey)
if err != nil {
return nil, "", errors.Wrap(err, "EncryptInit error")
}
ciphertext, err := p11ctx.Encrypt(session, plaintext)
if err != nil {
return nil, "", errors.Wrap(err, "Encrypt failed")
}
return ciphertext, hashalg, nil
}
// privateDecryptOAEP uses a pkcs11 URI describing a private key to OAEP decrypt a ciphertext
func privateDecryptOAEP(privKeyObj *Pkcs11KeyFileObject, ciphertext []byte, hashalg string) ([]byte, error) {
oldenv, err := setEnvVars(privKeyObj.Uri.GetEnvMap())
if err != nil {
return nil, err
}
defer restoreEnv(oldenv)
p11ctx, session, err := pkcs11UriLogin(privKeyObj.Uri, true)
if err != nil {
return nil, err
}
defer pkcs11Logout(p11ctx, session)
keyid, label, err := pkcs11UriGetKeyIdAndLabel(privKeyObj.Uri)
if err != nil {
return nil, err
}
p11PrivKey, err := findObject(p11ctx, session, pkcs11.CKO_PRIVATE_KEY, keyid, label)
if err != nil {
return nil, err
}
var oaep *pkcs11.OAEPParams
// the default is sha1
switch hashalg {
case "sha1", "":
oaep = OAEPSha1Params
case "sha256":
oaep = OAEPSha256Params
default:
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)
if err != nil {
return nil, errors.Wrapf(err, "DecryptInit failed")
}
plaintext, err := p11ctx.Decrypt(session, ciphertext)
if err != nil {
return nil, errors.Wrapf(err, "Decrypt failed")
}
return plaintext, err
}
//
// The following part deals with the JSON formatted message for multiple pkcs11 recipients
//
// Pkcs11Blob holds the encrypted blobs for all recipients; this is what we will put into the image's annotations
type Pkcs11Blob struct {
Version uint `json:"version"`
Recipients []Pkcs11Recipient `json:"recipients"`
}
// Pkcs11Recipient holds the b64-encoded and encrypted blob for a particular recipient
type Pkcs11Recipient struct {
Version uint `json:"version"`
Blob string `json:"blob"`
Hash string `json:"hash,omitempty"`
}
// EncryptMultiple encrypts for one or multiple pkcs11 devices; the public keys passed to this function
// may either be *rsa.PublicKey or *pkcs11uri.Pkcs11URI; the returned byte array is a JSON string of the
// following format:
// {
// recipients: [ // recipient list
// {
// "version": 0,
// "blob": <base64 encoded RSA OAEP encrypted blob>,
// "hash": <hash used for OAEP other than 'sha256'>
// } ,
// {
// "version": 0,
// "blob": <base64 encoded RSA OAEP encrypted blob>,
// "hash": <hash used for OAEP other than 'sha256'>
// } ,
// [...]
// ]
// }
func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
var (
ciphertext []byte
err error
pkcs11blob Pkcs11Blob = Pkcs11Blob{Version: 0}
hashalg string
)
for _, pubKey := range pubKeys {
switch pkey := pubKey.(type) {
case *rsa.PublicKey:
ciphertext, hashalg, err = rsaPublicEncryptOAEP(pkey, data)
case *Pkcs11KeyFileObject:
ciphertext, hashalg, err = publicEncryptOAEP(pkey, data)
default:
err = errors.Errorf("Unsupported key object type for pkcs11 public key")
}
if err != nil {
return nil, err
}
if hashalg == OAEPDefaultHash {
hashalg = ""
}
recipient := Pkcs11Recipient{
Version: 0,
Blob: base64.StdEncoding.EncodeToString(ciphertext),
Hash: hashalg,
}
pkcs11blob.Recipients = append(pkcs11blob.Recipients, recipient)
}
return json.Marshal(&pkcs11blob)
}
// Decrypt tries to decrypt one of the recipients' blobs using a pkcs11 private key.
// The input pkcs11blobstr is a string with the following format:
// {
// recipients: [ // recipient list
// {
// "version": 0,
// "blob": <base64 encoded RSA OAEP encrypted blob>,
// "hash": <hash used for OAEP other than 'sha256'>
// } ,
// {
// "version": 0,
// "blob": <base64 encoded RSA OAEP encrypted blob>,
// "hash": <hash used for OAEP other than 'sha256'>
// } ,
// [...]
// }
func Decrypt(privKeyObjs []*Pkcs11KeyFileObject, pkcs11blobstr []byte) ([]byte, error) {
pkcs11blob := Pkcs11Blob{}
err := json.Unmarshal(pkcs11blobstr, &pkcs11blob)
if err != nil {
return nil, errors.Wrapf(err, "Could not parse Pkcs11Blob")
}
switch pkcs11blob.Version {
case 0:
// latest supported version
default:
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
errs := ""
for _, recipient := range pkcs11blob.Recipients {
switch recipient.Version {
case 0:
// last supported version
default:
return nil, errors.Errorf("Found Pkcs11Recipient with version %d but maximum supported version is 0.", recipient.Version)
}
ciphertext, err := base64.StdEncoding.DecodeString(recipient.Blob)
if err != nil || len(ciphertext) == 0 {
// This should never happen... we skip over decoding issues
errs += fmt.Sprintf("Base64 decoding failed: %s\n", err)
continue
}
// try all keys until one works
for _, privKeyObj := range privKeyObjs {
plaintext, err := privateDecryptOAEP(privKeyObj, ciphertext, recipient.Hash)
if err == nil {
return plaintext, nil
}
if uri, err2 := privKeyObj.Uri.Format(); err2 == nil {
errs += fmt.Sprintf("%s : %s\n", uri, err)
} else {
errs += fmt.Sprintf("%s\n", err)
}
}
}
return nil, errors.Errorf("Could not find a pkcs11 key for decryption:\n%s", errs)
}

View File

@@ -0,0 +1,31 @@
// +build !cgo
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pkcs11
import (
"github.com/pkg/errors"
)
func EncryptMultiple(pubKeys []interface{}, data []byte) ([]byte, error) {
return nil, errors.Errorf("ocicrypt pkcs11 not supported on this build")
}
func Decrypt(privKeyObjs []*Pkcs11KeyFileObject, pkcs11blobstr []byte) ([]byte, error) {
return nil, errors.Errorf("ocicrypt pkcs11 not supported on this build")
}

View File

@@ -0,0 +1,114 @@
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pkcs11
import (
"os"
"runtime"
"strings"
"sync"
"github.com/pkg/errors"
)
var (
envLock sync.Mutex
)
// setEnvVars sets the environment variables given in the map and locks the environment from
// modification with the same function; if successful, you *must* call restoreEnv with the return
// value from this function
func setEnvVars(env map[string]string) ([]string, error) {
envLock.Lock()
if len(env) == 0 {
return nil, nil
}
oldenv := os.Environ()
for k, v := range env {
err := os.Setenv(k, v)
if err != nil {
restoreEnv(oldenv)
return nil, errors.Wrapf(err, "Could not set environment variable '%s' to '%s'", k, v)
}
}
return oldenv, nil
}
func arrayToMap(elements []string) map[string]string {
o := make(map[string]string)
for _, element := range elements {
p := strings.SplitN(element, "=", 2)
if len(p) == 2 {
o[p[0]] = p[1]
}
}
return o
}
// restoreEnv restores the environment to be exactly as given in the array of strings
// and unlocks the lock
func restoreEnv(envs []string) {
if envs != nil && len(envs) >= 0 {
target := arrayToMap(envs)
curr := arrayToMap(os.Environ())
for nc, vc := range curr {
vt, ok := target[nc]
if !ok {
os.Unsetenv(nc)
} else if vc == vt {
delete(target, nc)
}
}
for nt, vt := range target {
os.Setenv(nt, vt)
}
}
envLock.Unlock()
}
func getHostAndOsType() (string, string, string) {
ht := ""
ot := ""
st := ""
switch runtime.GOOS {
case "linux":
ot = "linux"
st = "gnu"
switch runtime.GOARCH {
case "arm":
ht = "arm"
case "arm64":
ht = "aarch64"
case "amd64":
ht = "x86_64"
case "ppc64le":
ht = "powerpc64le"
case "s390x":
ht = "s390x"
}
}
return ht, ot, st
}

View File

@@ -19,6 +19,9 @@ package ocicrypt
import (
"encoding/base64"
"encoding/json"
"fmt"
keyproviderconfig "github.com/containers/ocicrypt/config/keyprovider-config"
"github.com/containers/ocicrypt/keywrap/keyprovider"
"io"
"strings"
@@ -27,8 +30,10 @@ import (
"github.com/containers/ocicrypt/keywrap"
"github.com/containers/ocicrypt/keywrap/jwe"
"github.com/containers/ocicrypt/keywrap/pgp"
"github.com/containers/ocicrypt/keywrap/pkcs11"
"github.com/containers/ocicrypt/keywrap/pkcs7"
"github.com/opencontainers/go-digest"
log "github.com/sirupsen/logrus"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
@@ -43,6 +48,15 @@ func init() {
RegisterKeyWrapper("pgp", pgp.NewKeyWrapper())
RegisterKeyWrapper("jwe", jwe.NewKeyWrapper())
RegisterKeyWrapper("pkcs7", pkcs7.NewKeyWrapper())
RegisterKeyWrapper("pkcs11", pkcs11.NewKeyWrapper())
ic, err := keyproviderconfig.GetConfiguration()
if err != nil {
log.Error(err)
} else if ic != nil {
for provider, attrs := range ic.KeyProviderConfig {
RegisterKeyWrapper("provider."+provider, keyprovider.NewKeyWrapper(provider, attrs))
}
}
}
var keyWrappers map[string]keywrap.KeyWrapper
@@ -128,6 +142,7 @@ func EncryptLayer(ec *config.EncryptConfig, encOrPlainLayerReader io.Reader, des
}
newAnnotations := make(map[string]string)
keysWrapped := false
for annotationsID, scheme := range keyWrapperAnnotations {
b64Annotations := desc.Annotations[annotationsID]
keywrapper := GetKeyWrapper(scheme)
@@ -136,10 +151,14 @@ func EncryptLayer(ec *config.EncryptConfig, encOrPlainLayerReader io.Reader, des
return nil, err
}
if b64Annotations != "" {
keysWrapped = true
newAnnotations[annotationsID] = b64Annotations
}
}
if !keysWrapped {
return nil, errors.New("no wrapped keys produced by encryption")
}
newAnnotations["org.opencontainers.image.enc.pubopts"] = base64.StdEncoding.EncodeToString(pubOptsData)
if len(newAnnotations) == 0 {
@@ -191,6 +210,7 @@ func DecryptLayer(dc *config.DecryptConfig, encLayerReader io.Reader, desc ocisp
func decryptLayerKeyOptsData(dc *config.DecryptConfig, desc ocispec.Descriptor) ([]byte, error) {
privKeyGiven := false
errs := ""
for annotationsID, scheme := range keyWrapperAnnotations {
b64Annotation := desc.Annotations[annotationsID]
if b64Annotation != "" {
@@ -203,10 +223,10 @@ func decryptLayerKeyOptsData(dc *config.DecryptConfig, desc ocispec.Descriptor)
if len(keywrapper.GetPrivateKeys(dc.Parameters)) > 0 {
privKeyGiven = true
}
optsData, err := preUnwrapKey(keywrapper, dc, b64Annotation)
if err != nil {
// try next keywrap.KeyWrapper
errs += fmt.Sprintf("%s\n", err)
continue
}
if optsData == nil {
@@ -219,7 +239,7 @@ func decryptLayerKeyOptsData(dc *config.DecryptConfig, desc ocispec.Descriptor)
if !privKeyGiven {
return nil, errors.New("missing private key needed for decryption")
}
return nil, errors.Errorf("no suitable key unwrapper found or none of the private keys could be used for decryption")
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) {
@@ -237,6 +257,7 @@ func preUnwrapKey(keywrapper keywrap.KeyWrapper, dc *config.DecryptConfig, b64An
if b64Annotations == "" {
return nil, nil
}
errs := ""
for _, b64Annotation := range strings.Split(b64Annotations, ",") {
annotation, err := base64.StdEncoding.DecodeString(b64Annotation)
if err != nil {
@@ -244,11 +265,12 @@ func preUnwrapKey(keywrapper keywrap.KeyWrapper, dc *config.DecryptConfig, b64An
}
optsData, err := keywrapper.UnwrapKey(dc, annotation)
if err != nil {
errs += fmt.Sprintf("- %s\n", err)
continue
}
return optsData, nil
}
return nil, errors.New("no suitable key found for decrypting layer key")
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

View File

@@ -3,16 +3,19 @@ module github.com/containers/ocicrypt
go 1.12
require (
github.com/containerd/containerd v1.2.10
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa
github.com/opencontainers/go-digest v1.0.0-rc1
github.com/golang/protobuf v1.4.3
github.com/google/go-cmp v0.5.2 // indirect
github.com/miekg/pkcs11 v1.0.3
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.1
github.com/pkg/errors v0.8.1
github.com/sirupsen/logrus v1.4.2 // indirect
github.com/stretchr/testify v1.3.0 // indirect
github.com/urfave/cli v1.22.1
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
google.golang.org/grpc v1.24.0 // indirect
gopkg.in/square/go-jose.v2 v2.3.1
gotest.tools v2.2.0+incompatible // indirect
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.7.0
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980
github.com/stretchr/testify v1.3.0
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
golang.org/x/sys v0.0.0-20200817155316-9781c653f443 // indirect
google.golang.org/grpc v1.33.2
gopkg.in/square/go-jose.v2 v2.5.1
gopkg.in/yaml.v2 v2.3.0
)

View File

@@ -1,73 +1,116 @@
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/containerd/containerd v1.2.10 h1:liQDhXqIn7y6cJ/7qBgOaZsiTZJc56/wkkhDBiDBRDw=
github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/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/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
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.0.3 h1:iMwmD7I5225wv84WxIG/bmxz9AXjWvTWIbM/TYHvWtw=
github.com/miekg/pkcs11 v1.0.3/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/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
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-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200817155316-9781c653f443 h1:X18bCaipMcoJGm27Nv7zr4XYPKGUy92GtqboKC2Hxaw=
golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s=
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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=

View File

@@ -170,7 +170,7 @@ func (gc *gpgv2Client) getKeyDetails(option string, keyid uint64) ([]byte, bool,
var args []string
if gc.gpgHomeDir != "" {
args = append([]string{"--homedir", gc.gpgHomeDir})
args = []string{"--homedir", gc.gpgHomeDir}
}
args = append(args, option, fmt.Sprintf("0x%x", keyid))
@@ -180,13 +180,13 @@ func (gc *gpgv2Client) getKeyDetails(option string, keyid uint64) ([]byte, bool,
return keydata, err == nil, err
}
// GetSecretKeyDetails retrives the secret key details of key with keyid.
// GetSecretKeyDetails retrieves the secret key details of key with keyid.
// returns a byte array of the details and a bool if the key exists
func (gc *gpgv2Client) GetSecretKeyDetails(keyid uint64) ([]byte, bool, error) {
return gc.getKeyDetails("-K", keyid)
}
// GetKeyDetails retrives the public key details of key with keyid.
// GetKeyDetails retrieves the public key details of key with keyid.
// returns a byte array of the details and a bool if the key exists
func (gc *gpgv2Client) GetKeyDetails(keyid uint64) ([]byte, bool, error) {
return gc.getKeyDetails("-k", keyid)
@@ -229,7 +229,7 @@ func (gc *gpgv1Client) getKeyDetails(option string, keyid uint64) ([]byte, bool,
var args []string
if gc.gpgHomeDir != "" {
args = append([]string{"--homedir", gc.gpgHomeDir})
args = []string{"--homedir", gc.gpgHomeDir}
}
args = append(args, option, fmt.Sprintf("0x%x", keyid))
@@ -240,13 +240,13 @@ func (gc *gpgv1Client) getKeyDetails(option string, keyid uint64) ([]byte, bool,
return keydata, err == nil, err
}
// GetSecretKeyDetails retrives the secret key details of key with keyid.
// GetSecretKeyDetails retrieves the secret key details of key with keyid.
// returns a byte array of the details and a bool if the key exists
func (gc *gpgv1Client) GetSecretKeyDetails(keyid uint64) ([]byte, bool, error) {
return gc.getKeyDetails("-K", keyid)
}
// GetKeyDetails retrives the public key details of key with keyid.
// GetKeyDetails retrieves the public key details of key with keyid.
// returns a byte array of the details and a bool if the key exists
func (gc *gpgv1Client) GetKeyDetails(keyid uint64) ([]byte, bool, error) {
return gc.getKeyDetails("-k", keyid)

View File

@@ -0,0 +1,242 @@
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package keyprovider
import (
"context"
"encoding/json"
"github.com/containers/ocicrypt/config"
keyproviderconfig "github.com/containers/ocicrypt/config/keyprovider-config"
"github.com/containers/ocicrypt/keywrap"
"github.com/containers/ocicrypt/utils"
keyproviderpb "github.com/containers/ocicrypt/utils/keyprovider"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
)
type keyProviderKeyWrapper struct {
provider string
attrs keyproviderconfig.KeyProviderAttrs
}
func (kw *keyProviderKeyWrapper) GetAnnotationID() string {
return "org.opencontainers.image.enc.keys.provider." + kw.provider
}
// NewKeyWrapper returns a new key wrapping interface using keyprovider
func NewKeyWrapper(p string, a keyproviderconfig.KeyProviderAttrs) keywrap.KeyWrapper {
return &keyProviderKeyWrapper{provider: p, attrs: a}
}
type KeyProviderKeyWrapProtocolOperation string
var (
OpKeyWrap KeyProviderKeyWrapProtocolOperation = "keywrap"
OpKeyUnwrap KeyProviderKeyWrapProtocolOperation = "keyunwrap"
)
// KeyProviderKeyWrapProtocolInput defines the input to the key provider binary or grpc method.
type KeyProviderKeyWrapProtocolInput struct {
// Operation is either "keywrap" or "keyunwrap"
Operation KeyProviderKeyWrapProtocolOperation `json:"op"`
// KeyWrapParams encodes the arguments to key wrap if operation is set to wrap
KeyWrapParams KeyWrapParams `json:"keywrapparams,omitempty"`
// KeyUnwrapParams encodes the arguments to key unwrap if operation is set to unwrap
KeyUnwrapParams KeyUnwrapParams `json:"keyunwrapparams,omitempty"`
}
// KeyProviderKeyWrapProtocolOutput defines the output of the key provider binary or grpc method.
type KeyProviderKeyWrapProtocolOutput struct {
// KeyWrapResult encodes the results to key wrap if operation is to wrap
KeyWrapResults KeyWrapResults `json:"keywrapresults,omitempty"`
// KeyUnwrapResult encodes the result to key unwrap if operation is to unwrap
KeyUnwrapResults KeyUnwrapResults `json:"keyunwrapresults,omitempty"`
}
type KeyWrapParams struct {
Ec *config.EncryptConfig `json:"ec"`
OptsData []byte `json:"optsdata"`
}
type KeyUnwrapParams struct {
Dc *config.DecryptConfig `json:"dc"`
Annotation []byte `json:"annotation"`
}
type KeyUnwrapResults struct {
OptsData []byte `json:"optsdata"`
}
type KeyWrapResults struct {
Annotation []byte `json:"annotation"`
}
var runner utils.CommandExecuter
func init() {
runner = utils.Runner{}
}
// WrapKeys calls appropriate binary executable/grpc server for wrapping the session key for recipients and gets encrypted optsData, which
// describe the symmetric key used for encrypting the layer
func (kw *keyProviderKeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
input, err := json.Marshal(KeyProviderKeyWrapProtocolInput{
Operation: OpKeyWrap,
KeyWrapParams: KeyWrapParams{
Ec: ec,
OptsData: optsData,
},
})
if err != nil {
return nil, err
}
if _, ok := ec.Parameters[kw.provider]; ok {
if kw.attrs.Command != nil {
protocolOuput, err := getProviderCommandOutput(input, kw.attrs.Command)
if err != nil {
return nil, errors.Wrap(err, "error while retrieving keyprovider protocol command output")
}
return protocolOuput.KeyWrapResults.Annotation, nil
} else if kw.attrs.Grpc != "" {
protocolOuput, err := getProviderGRPCOutput(input, kw.attrs.Grpc, OpKeyWrap)
if err != nil {
return nil, errors.Wrap(err, "error while retrieving keyprovider protocol grpc output")
}
return protocolOuput.KeyWrapResults.Annotation, nil
} else {
return nil, errors.New("Unsupported keyprovider invocation. Supported invocation methods are grpc and cmd")
}
}
return nil, nil
}
// UnwrapKey calls appropriate binary executable/grpc server for unwrapping the session key based on the protocol given in annotation for recipients and gets decrypted optsData,
// which describe the symmetric key used for decrypting the layer
func (kw *keyProviderKeyWrapper) UnwrapKey(dc *config.DecryptConfig, jsonString []byte) ([]byte, error) {
input, err := json.Marshal(KeyProviderKeyWrapProtocolInput{
Operation: OpKeyUnwrap,
KeyUnwrapParams: KeyUnwrapParams{
Dc: dc,
Annotation: jsonString,
},
})
if err != nil {
return nil, err
}
if kw.attrs.Command != nil {
protocolOuput, err := getProviderCommandOutput(input, kw.attrs.Command)
if err != nil {
// If err is not nil, then ignore it and continue with rest of the given keyproviders
return nil, err
}
return protocolOuput.KeyUnwrapResults.OptsData, nil
} else if kw.attrs.Grpc != "" {
protocolOuput, err := getProviderGRPCOutput(input, kw.attrs.Grpc, OpKeyUnwrap)
if err != nil {
// If err is not nil, then ignore it and continue with rest of the given keyproviders
return nil, err
}
return protocolOuput.KeyUnwrapResults.OptsData, nil
} else {
return nil, errors.New("Unsupported keyprovider invocation. Supported invocation methods are grpc and cmd")
}
}
func getProviderGRPCOutput(input []byte, connString string, operation KeyProviderKeyWrapProtocolOperation) (*KeyProviderKeyWrapProtocolOutput, error) {
var protocolOuput KeyProviderKeyWrapProtocolOutput
var grpcOutput *keyproviderpb.KeyProviderKeyWrapProtocolOutput
cc, err := grpc.Dial(connString, grpc.WithInsecure())
if err != nil {
return nil, errors.Wrap(err, "error while dialing rpc server")
}
defer func() {
derr := cc.Close()
if derr != nil {
log.WithError(derr).Error("Error closing grpc socket")
}
}()
client := keyproviderpb.NewKeyProviderServiceClient(cc)
req := &keyproviderpb.KeyProviderKeyWrapProtocolInput{
KeyProviderKeyWrapProtocolInput: input,
}
if operation == OpKeyWrap {
grpcOutput, err = client.WrapKey(context.Background(), req)
if err != nil {
return nil, errors.Wrap(err, "Error from grpc method")
}
} else if operation == OpKeyUnwrap {
grpcOutput, err = client.UnWrapKey(context.Background(), req)
if err != nil {
return nil, errors.Wrap(err, "Error from grpc method")
}
} else {
return nil, errors.New("Unsupported operation")
}
respBytes := grpcOutput.GetKeyProviderKeyWrapProtocolOutput()
err = json.Unmarshal(respBytes, &protocolOuput)
if err != nil {
return nil, errors.Wrap(err, "Error while unmarshalling grpc method output")
}
return &protocolOuput, nil
}
func getProviderCommandOutput(input []byte, command *keyproviderconfig.Command) (*KeyProviderKeyWrapProtocolOutput, error) {
var protocolOuput KeyProviderKeyWrapProtocolOutput
// Convert interface to command structure
respBytes, err := runner.Exec(command.Path, command.Args, input)
if err != nil {
return nil, err
}
err = json.Unmarshal(respBytes, &protocolOuput)
if err != nil {
return nil, errors.Wrap(err, "Error while unmarshalling binary executable command output")
}
return &protocolOuput, nil
}
// Return false as it is not applicable to keyprovider protocol
func (kw *keyProviderKeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool {
return false
}
// Return nil as it is not applicable to keyprovider protocol
func (kw *keyProviderKeyWrapper) GetPrivateKeys(dcparameters map[string][][]byte) [][]byte {
return nil
}
// Return nil as it is not applicable to keyprovider protocol
func (kw *keyProviderKeyWrapper) GetKeyIdsFromPacket(_ string) ([]uint64, error) {
return nil, nil
}
// Return nil as it is not applicable to keyprovider protocol
func (kw *keyProviderKeyWrapper) GetRecipients(_ string) ([]string, error) {
return nil, nil
}

View File

@@ -0,0 +1,147 @@
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pkcs11
import (
"github.com/containers/ocicrypt/config"
"github.com/containers/ocicrypt/crypto/pkcs11"
"github.com/containers/ocicrypt/keywrap"
"github.com/containers/ocicrypt/utils"
"github.com/pkg/errors"
)
type pkcs11KeyWrapper struct {
}
func (kw *pkcs11KeyWrapper) GetAnnotationID() string {
return "org.opencontainers.image.enc.keys.pkcs11"
}
// NewKeyWrapper returns a new key wrapping interface using pkcs11
func NewKeyWrapper() keywrap.KeyWrapper {
return &pkcs11KeyWrapper{}
}
// WrapKeys wraps the session key for recpients and encrypts the optsData, which
// describe the symmetric key used for encrypting the layer
func (kw *pkcs11KeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
pkcs11Recipients, err := addPubKeys(&ec.DecryptConfig, append(ec.Parameters["pkcs11-pubkeys"], ec.Parameters["pkcs11-yamls"]...))
if err != nil {
return nil, err
}
// no recipients is not an error...
if len(pkcs11Recipients) == 0 {
return nil, nil
}
jsonString, err := pkcs11.EncryptMultiple(pkcs11Recipients, optsData)
if err != nil {
return nil, errors.Wrapf(err, "PKCS11 EncryptMulitple failed")
}
return jsonString, nil
}
func (kw *pkcs11KeyWrapper) UnwrapKey(dc *config.DecryptConfig, jsonString []byte) ([]byte, error) {
var pkcs11PrivKeys []*pkcs11.Pkcs11KeyFileObject
privKeys := kw.GetPrivateKeys(dc.Parameters)
if len(privKeys) == 0 {
return nil, errors.New("No private keys found for PKCS11 decryption")
}
p11conf, err := p11confFromParameters(dc.Parameters)
if err != nil {
return nil, err
}
for _, privKey := range privKeys {
key, err := utils.ParsePrivateKey(privKey, nil, "PKCS11")
if err != nil {
return nil, err
}
switch pkcs11PrivKey := key.(type) {
case *pkcs11.Pkcs11KeyFileObject:
if p11conf != nil {
pkcs11PrivKey.Uri.SetModuleDirectories(p11conf.ModuleDirectories)
pkcs11PrivKey.Uri.SetAllowedModulePaths(p11conf.AllowedModulePaths)
}
pkcs11PrivKeys = append(pkcs11PrivKeys, pkcs11PrivKey)
default:
continue
}
}
plaintext, err := pkcs11.Decrypt(pkcs11PrivKeys, jsonString)
if err == nil {
return plaintext, nil
}
return nil, errors.Wrapf(err, "PKCS11: No suitable private key found for decryption")
}
func (kw *pkcs11KeyWrapper) NoPossibleKeys(dcparameters map[string][][]byte) bool {
return len(kw.GetPrivateKeys(dcparameters)) == 0
}
func (kw *pkcs11KeyWrapper) GetPrivateKeys(dcparameters map[string][][]byte) [][]byte {
return dcparameters["pkcs11-yamls"]
}
func (kw *pkcs11KeyWrapper) GetKeyIdsFromPacket(_ string) ([]uint64, error) {
return nil, nil
}
func (kw *pkcs11KeyWrapper) GetRecipients(_ string) ([]string, error) {
return []string{"[pkcs11]"}, nil
}
func addPubKeys(dc *config.DecryptConfig, pubKeys [][]byte) ([]interface{}, error) {
var pkcs11Keys []interface{}
if len(pubKeys) == 0 {
return pkcs11Keys, nil
}
p11conf, err := p11confFromParameters(dc.Parameters)
if err != nil {
return nil, err
}
for _, pubKey := range pubKeys {
key, err := utils.ParsePublicKey(pubKey, "PKCS11")
if err != nil {
return nil, err
}
switch pkcs11PubKey := key.(type) {
case *pkcs11.Pkcs11KeyFileObject:
if p11conf != nil {
pkcs11PubKey.Uri.SetModuleDirectories(p11conf.ModuleDirectories)
pkcs11PubKey.Uri.SetAllowedModulePaths(p11conf.AllowedModulePaths)
}
}
pkcs11Keys = append(pkcs11Keys, key)
}
return pkcs11Keys, nil
}
func p11confFromParameters(dcparameters map[string][][]byte) (*pkcs11.Pkcs11Config, error){
if _, ok := dcparameters["pkcs11-config"]; ok {
return pkcs11.ParsePkcs11ConfigFile(dcparameters["pkcs11-config"][0])
}
return nil, nil
}

View File

@@ -23,8 +23,8 @@ import (
"github.com/containers/ocicrypt/config"
"github.com/containers/ocicrypt/keywrap"
"github.com/containers/ocicrypt/utils"
"github.com/fullsailor/pkcs7"
"github.com/pkg/errors"
"go.mozilla.org/pkcs7"
)
type pkcs7KeyWrapper struct {

View File

@@ -17,7 +17,10 @@
package utils
import (
"bytes"
"io"
"os/exec"
"github.com/pkg/errors"
)
// FillBuffer fills the given buffer with as many bytes from the reader as possible. It returns
@@ -29,3 +32,25 @@ func FillBuffer(reader io.Reader, buffer []byte) (int, error) {
}
return n, err
}
// first argument is the command, like cat or echo,
// the second is the list of args to pass to it
type CommandExecuter interface {
Exec(string, []string, []byte) ([]byte, error)
}
type Runner struct{}
// ExecuteCommand is used to execute a linux command line command and return the output of the command with an error if it exists.
func (r Runner) Exec(cmdName string, args []string, input []byte) ([]byte, error) {
var out bytes.Buffer
stdInputBuffer := bytes.NewBuffer(input)
cmd := exec.Command(cmdName, args...)
cmd.Stdin = stdInputBuffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return nil, errors.Wrapf(err, "Error while running command: %s", cmdName)
}
return out.Bytes(), nil
}

View File

@@ -0,0 +1,243 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: keyprovider.proto
package keyprovider
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type KeyProviderKeyWrapProtocolInput struct {
KeyProviderKeyWrapProtocolInput []byte `protobuf:"bytes,1,opt,name=KeyProviderKeyWrapProtocolInput,proto3" json:"KeyProviderKeyWrapProtocolInput,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *KeyProviderKeyWrapProtocolInput) Reset() { *m = KeyProviderKeyWrapProtocolInput{} }
func (m *KeyProviderKeyWrapProtocolInput) String() string { return proto.CompactTextString(m) }
func (*KeyProviderKeyWrapProtocolInput) ProtoMessage() {}
func (*KeyProviderKeyWrapProtocolInput) Descriptor() ([]byte, []int) {
return fileDescriptor_da74c8e785ad390c, []int{0}
}
func (m *KeyProviderKeyWrapProtocolInput) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_KeyProviderKeyWrapProtocolInput.Unmarshal(m, b)
}
func (m *KeyProviderKeyWrapProtocolInput) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_KeyProviderKeyWrapProtocolInput.Marshal(b, m, deterministic)
}
func (m *KeyProviderKeyWrapProtocolInput) XXX_Merge(src proto.Message) {
xxx_messageInfo_KeyProviderKeyWrapProtocolInput.Merge(m, src)
}
func (m *KeyProviderKeyWrapProtocolInput) XXX_Size() int {
return xxx_messageInfo_KeyProviderKeyWrapProtocolInput.Size(m)
}
func (m *KeyProviderKeyWrapProtocolInput) XXX_DiscardUnknown() {
xxx_messageInfo_KeyProviderKeyWrapProtocolInput.DiscardUnknown(m)
}
var xxx_messageInfo_KeyProviderKeyWrapProtocolInput proto.InternalMessageInfo
func (m *KeyProviderKeyWrapProtocolInput) GetKeyProviderKeyWrapProtocolInput() []byte {
if m != nil {
return m.KeyProviderKeyWrapProtocolInput
}
return nil
}
type KeyProviderKeyWrapProtocolOutput struct {
KeyProviderKeyWrapProtocolOutput []byte `protobuf:"bytes,1,opt,name=KeyProviderKeyWrapProtocolOutput,proto3" json:"KeyProviderKeyWrapProtocolOutput,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *KeyProviderKeyWrapProtocolOutput) Reset() { *m = KeyProviderKeyWrapProtocolOutput{} }
func (m *KeyProviderKeyWrapProtocolOutput) String() string { return proto.CompactTextString(m) }
func (*KeyProviderKeyWrapProtocolOutput) ProtoMessage() {}
func (*KeyProviderKeyWrapProtocolOutput) Descriptor() ([]byte, []int) {
return fileDescriptor_da74c8e785ad390c, []int{1}
}
func (m *KeyProviderKeyWrapProtocolOutput) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_KeyProviderKeyWrapProtocolOutput.Unmarshal(m, b)
}
func (m *KeyProviderKeyWrapProtocolOutput) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_KeyProviderKeyWrapProtocolOutput.Marshal(b, m, deterministic)
}
func (m *KeyProviderKeyWrapProtocolOutput) XXX_Merge(src proto.Message) {
xxx_messageInfo_KeyProviderKeyWrapProtocolOutput.Merge(m, src)
}
func (m *KeyProviderKeyWrapProtocolOutput) XXX_Size() int {
return xxx_messageInfo_KeyProviderKeyWrapProtocolOutput.Size(m)
}
func (m *KeyProviderKeyWrapProtocolOutput) XXX_DiscardUnknown() {
xxx_messageInfo_KeyProviderKeyWrapProtocolOutput.DiscardUnknown(m)
}
var xxx_messageInfo_KeyProviderKeyWrapProtocolOutput proto.InternalMessageInfo
func (m *KeyProviderKeyWrapProtocolOutput) GetKeyProviderKeyWrapProtocolOutput() []byte {
if m != nil {
return m.KeyProviderKeyWrapProtocolOutput
}
return nil
}
func init() {
proto.RegisterType((*KeyProviderKeyWrapProtocolInput)(nil), "keyprovider.keyProviderKeyWrapProtocolInput")
proto.RegisterType((*KeyProviderKeyWrapProtocolOutput)(nil), "keyprovider.keyProviderKeyWrapProtocolOutput")
}
func init() {
proto.RegisterFile("keyprovider.proto", fileDescriptor_da74c8e785ad390c)
}
var fileDescriptor_da74c8e785ad390c = []byte{
// 169 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x12, 0xcc, 0x4e, 0xad, 0x2c,
0x28, 0xca, 0x2f, 0xcb, 0x4c, 0x49, 0x2d, 0xd2, 0x03, 0x32, 0x4a, 0xf2, 0x85, 0xb8, 0x91, 0x84,
0x94, 0xb2, 0xb9, 0xe4, 0x81, 0xdc, 0x00, 0x28, 0xd7, 0x3b, 0xb5, 0x32, 0xbc, 0x28, 0xb1, 0x20,
0x00, 0xa4, 0x2e, 0x39, 0x3f, 0xc7, 0x33, 0xaf, 0xa0, 0xb4, 0x44, 0xc8, 0x83, 0x4b, 0xde, 0x1b,
0xbf, 0x12, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x9e, 0x20, 0x42, 0xca, 0x94, 0xf2, 0xb8, 0x14, 0x70,
0x5b, 0xe6, 0x5f, 0x5a, 0x02, 0xb2, 0xcd, 0x8b, 0x4b, 0xc1, 0x9b, 0x80, 0x1a, 0xa8, 0x75, 0x04,
0xd5, 0x19, 0xbd, 0x62, 0xe4, 0x12, 0x42, 0x52, 0x14, 0x9c, 0x5a, 0x54, 0x96, 0x99, 0x9c, 0x2a,
0x94, 0xc1, 0xc5, 0x0e, 0x52, 0x0c, 0x94, 0x11, 0xd2, 0xd1, 0x43, 0x0e, 0x1f, 0x02, 0x21, 0x21,
0xa5, 0x4b, 0xa4, 0x6a, 0x88, 0xf5, 0x4a, 0x0c, 0x42, 0x59, 0x5c, 0x9c, 0xa1, 0x79, 0xf4, 0xb1,
0xcb, 0x89, 0x37, 0x0a, 0x39, 0x62, 0x93, 0xd8, 0xc0, 0x91, 0x6d, 0x0c, 0x08, 0x00, 0x00, 0xff,
0xff, 0x9a, 0x10, 0xcb, 0xf9, 0x01, 0x02, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// KeyProviderServiceClient is the client API for KeyProviderService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type KeyProviderServiceClient interface {
WrapKey(ctx context.Context, in *KeyProviderKeyWrapProtocolInput, opts ...grpc.CallOption) (*KeyProviderKeyWrapProtocolOutput, error)
UnWrapKey(ctx context.Context, in *KeyProviderKeyWrapProtocolInput, opts ...grpc.CallOption) (*KeyProviderKeyWrapProtocolOutput, error)
}
type keyProviderServiceClient struct {
cc grpc.ClientConnInterface
}
func NewKeyProviderServiceClient(cc grpc.ClientConnInterface) KeyProviderServiceClient {
return &keyProviderServiceClient{cc}
}
func (c *keyProviderServiceClient) WrapKey(ctx context.Context, in *KeyProviderKeyWrapProtocolInput, opts ...grpc.CallOption) (*KeyProviderKeyWrapProtocolOutput, error) {
out := new(KeyProviderKeyWrapProtocolOutput)
err := c.cc.Invoke(ctx, "/keyprovider.KeyProviderService/WrapKey", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *keyProviderServiceClient) UnWrapKey(ctx context.Context, in *KeyProviderKeyWrapProtocolInput, opts ...grpc.CallOption) (*KeyProviderKeyWrapProtocolOutput, error) {
out := new(KeyProviderKeyWrapProtocolOutput)
err := c.cc.Invoke(ctx, "/keyprovider.KeyProviderService/UnWrapKey", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// KeyProviderServiceServer is the server API for KeyProviderService service.
type KeyProviderServiceServer interface {
WrapKey(context.Context, *KeyProviderKeyWrapProtocolInput) (*KeyProviderKeyWrapProtocolOutput, error)
UnWrapKey(context.Context, *KeyProviderKeyWrapProtocolInput) (*KeyProviderKeyWrapProtocolOutput, error)
}
// UnimplementedKeyProviderServiceServer can be embedded to have forward compatible implementations.
type UnimplementedKeyProviderServiceServer struct {
}
func (*UnimplementedKeyProviderServiceServer) WrapKey(ctx context.Context, req *KeyProviderKeyWrapProtocolInput) (*KeyProviderKeyWrapProtocolOutput, error) {
return nil, status.Errorf(codes.Unimplemented, "method WrapKey not implemented")
}
func (*UnimplementedKeyProviderServiceServer) UnWrapKey(ctx context.Context, req *KeyProviderKeyWrapProtocolInput) (*KeyProviderKeyWrapProtocolOutput, error) {
return nil, status.Errorf(codes.Unimplemented, "method UnWrapKey not implemented")
}
func RegisterKeyProviderServiceServer(s *grpc.Server, srv KeyProviderServiceServer) {
s.RegisterService(&_KeyProviderService_serviceDesc, srv)
}
func _KeyProviderService_WrapKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(KeyProviderKeyWrapProtocolInput)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(KeyProviderServiceServer).WrapKey(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/keyprovider.KeyProviderService/WrapKey",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(KeyProviderServiceServer).WrapKey(ctx, req.(*KeyProviderKeyWrapProtocolInput))
}
return interceptor(ctx, in, info, handler)
}
func _KeyProviderService_UnWrapKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(KeyProviderKeyWrapProtocolInput)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(KeyProviderServiceServer).UnWrapKey(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/keyprovider.KeyProviderService/UnWrapKey",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(KeyProviderServiceServer).UnWrapKey(ctx, req.(*KeyProviderKeyWrapProtocolInput))
}
return interceptor(ctx, in, info, handler)
}
var _KeyProviderService_serviceDesc = grpc.ServiceDesc{
ServiceName: "keyprovider.KeyProviderService",
HandlerType: (*KeyProviderServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "WrapKey",
Handler: _KeyProviderService_WrapKey_Handler,
},
{
MethodName: "UnWrapKey",
Handler: _KeyProviderService_UnWrapKey_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "keyprovider.proto",
}

View File

@@ -0,0 +1,17 @@
syntax = "proto3";
package keyprovider;
option go_package = "keyprovider";
message keyProviderKeyWrapProtocolInput {
bytes KeyProviderKeyWrapProtocolInput = 1;
}
message keyProviderKeyWrapProtocolOutput {
bytes KeyProviderKeyWrapProtocolOutput = 1;
}
service KeyProviderService {
rpc WrapKey(keyProviderKeyWrapProtocolInput) returns (keyProviderKeyWrapProtocolOutput) {};
rpc UnWrapKey(keyProviderKeyWrapProtocolInput) returns (keyProviderKeyWrapProtocolOutput) {};
}

View File

@@ -24,6 +24,8 @@ import (
"fmt"
"strings"
"github.com/containers/ocicrypt/crypto/pkcs11"
"github.com/pkg/errors"
"golang.org/x/crypto/openpgp"
json "gopkg.in/square/go-jose.v2"
@@ -55,6 +57,18 @@ func parseJWKPublicKey(privKey []byte, prefix string) (interface{}, error) {
return &jwk, nil
}
// parsePkcs11PrivateKeyYaml parses the input byte array as pkcs11 key file yaml format)
func parsePkcs11PrivateKeyYaml(yaml []byte, prefix string) (*pkcs11.Pkcs11KeyFileObject, error) {
// if the URI does not have enough attributes, we will throw an error when decrypting
return pkcs11.ParsePkcs11KeyFile(yaml)
}
// parsePkcs11URIPublicKey parses the input byte array as a pkcs11 key file yaml
func parsePkcs11PublicKeyYaml(yaml []byte, prefix string) (*pkcs11.Pkcs11KeyFileObject, error) {
// if the URI does not have enough attributes, we will throw an error when decrypting
return pkcs11.ParsePkcs11KeyFile(yaml)
}
// IsPasswordError checks whether an error is related to a missing or wrong
// password
func IsPasswordError(err error) bool {
@@ -102,6 +116,9 @@ func ParsePrivateKey(privKey, privKeyPassword []byte, prefix string) (interface{
}
} else {
key, err = parseJWKPrivateKey(privKey, prefix)
if err != nil {
key, err = parsePkcs11PrivateKeyYaml(privKey, prefix)
}
}
}
return key, err
@@ -114,6 +131,11 @@ func IsPrivateKey(data []byte, password []byte) (bool, error) {
return err == nil, err
}
// IsPkcs11PrivateKey returns true in case the given byte array represents a pkcs11 private key
func IsPkcs11PrivateKey(data []byte) bool {
return pkcs11.IsPkcs11PrivateKey(data)
}
// ParsePublicKey tries to parse a public key in DER format first and
// PEM format after, returning an error if the parsing failed
func ParsePublicKey(pubKey []byte, prefix string) (interface{}, error) {
@@ -127,6 +149,9 @@ func ParsePublicKey(pubKey []byte, prefix string) (interface{}, error) {
}
} else {
key, err = parseJWKPublicKey(pubKey, prefix)
if err != nil {
key, err = parsePkcs11PublicKeyYaml(pubKey, prefix)
}
}
}
return key, err
@@ -138,6 +163,11 @@ func IsPublicKey(data []byte) bool {
return err == nil
}
// IsPkcs11PublicKey returns true in case the given byte array represents a pkcs11 public key
func IsPkcs11PublicKey(data []byte) bool {
return pkcs11.IsPkcs11PublicKey(data)
}
// ParseCertificate tries to parse a public key in DER format first and
// PEM format after, returning an error if the parsing failed
func ParseCertificate(certBytes []byte, prefix string) (*x509.Certificate, error) {