build(deps): bump github.com/containers/image/v5 from 5.0.0 to 5.1.0

Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.0.0 to 5.1.0.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.0.0...v5.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2019-12-19 13:29:25 -05:00
parent a359ca0d18
commit 50ece79387
181 changed files with 19733 additions and 2924 deletions

View File

@@ -0,0 +1,132 @@
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package jwe
import (
"crypto/ecdsa"
"github.com/containers/ocicrypt/config"
"github.com/containers/ocicrypt/keywrap"
"github.com/containers/ocicrypt/utils"
"github.com/pkg/errors"
jose "gopkg.in/square/go-jose.v2"
)
type jweKeyWrapper struct {
}
func (kw *jweKeyWrapper) GetAnnotationID() string {
return "org.opencontainers.image.enc.keys.jwe"
}
// NewKeyWrapper returns a new key wrapping interface using jwe
func NewKeyWrapper() keywrap.KeyWrapper {
return &jweKeyWrapper{}
}
// WrapKeys wraps the session key for recpients and encrypts the optsData, which
// describe the symmetric key used for encrypting the layer
func (kw *jweKeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
var joseRecipients []jose.Recipient
err := addPubKeys(&joseRecipients, ec.Parameters["pubkeys"])
if err != nil {
return nil, err
}
// no recipients is not an error...
if len(joseRecipients) == 0 {
return nil, nil
}
encrypter, err := jose.NewMultiEncrypter(jose.A256GCM, joseRecipients, nil)
if err != nil {
return nil, errors.Wrapf(err, "jose.NewMultiEncrypter failed")
}
jwe, err := encrypter.Encrypt(optsData)
if err != nil {
return nil, errors.Wrapf(err, "JWE Encrypt failed")
}
return []byte(jwe.FullSerialize()), nil
}
func (kw *jweKeyWrapper) UnwrapKey(dc *config.DecryptConfig, jweString []byte) ([]byte, error) {
jwe, err := jose.ParseEncrypted(string(jweString))
if err != nil {
return nil, errors.New("jose.ParseEncrypted failed")
}
privKeys := kw.GetPrivateKeys(dc.Parameters)
if len(privKeys) == 0 {
return nil, errors.New("No private keys found for JWE decryption")
}
privKeysPasswords := kw.getPrivateKeysPasswords(dc.Parameters)
if len(privKeysPasswords) != len(privKeys) {
return nil, errors.New("Private key password array length must be same as that of private keys")
}
for idx, privKey := range privKeys {
key, err := utils.ParsePrivateKey(privKey, privKeysPasswords[idx], "JWE")
if err != nil {
return nil, err
}
_, _, plain, err := jwe.DecryptMulti(key)
if err == nil {
return plain, nil
}
}
return nil, errors.New("JWE: No suitable private key found for decryption")
}
func (kw *jweKeyWrapper) GetPrivateKeys(dcparameters map[string][][]byte) [][]byte {
return dcparameters["privkeys"]
}
func (kw *jweKeyWrapper) getPrivateKeysPasswords(dcparameters map[string][][]byte) [][]byte {
return dcparameters["privkeys-passwords"]
}
func (kw *jweKeyWrapper) GetKeyIdsFromPacket(b64jwes string) ([]uint64, error) {
return nil, nil
}
func (kw *jweKeyWrapper) GetRecipients(b64jwes string) ([]string, error) {
return []string{"[jwe]"}, nil
}
func addPubKeys(joseRecipients *[]jose.Recipient, pubKeys [][]byte) error {
if len(pubKeys) == 0 {
return nil
}
for _, pubKey := range pubKeys {
key, err := utils.ParsePublicKey(pubKey, "JWE")
if err != nil {
return err
}
alg := jose.RSA_OAEP
switch key.(type) {
case *ecdsa.PublicKey:
alg = jose.ECDH_ES_A256KW
}
*joseRecipients = append(*joseRecipients, jose.Recipient{
Algorithm: alg,
Key: key,
})
}
return nil
}

View File

@@ -0,0 +1,40 @@
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package keywrap
import (
"github.com/containers/ocicrypt/config"
)
// KeyWrapper is the interface used for wrapping keys using
// a specific encryption technology (pgp, jwe)
type KeyWrapper interface {
WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error)
UnwrapKey(dc *config.DecryptConfig, annotation []byte) ([]byte, error)
GetAnnotationID() string
// GetPrivateKeys (optional) gets the array of private keys. It is an optional implementation
// as in some key services, a private key may not be exportable (i.e. HSM)
GetPrivateKeys(dcparameters map[string][][]byte) [][]byte
// GetKeyIdsFromPacket (optional) gets a list of key IDs. This is optional as some encryption
// schemes may not have a notion of key IDs
GetKeyIdsFromPacket(packet string) ([]uint64, error)
// GetRecipients (optional) gets a list of recipients. It is optional due to the validity of
// recipients in a particular encryptiong scheme
GetRecipients(packet string) ([]string, error)
}

View File

@@ -0,0 +1,269 @@
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pgp
import (
"bytes"
"crypto"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"net/mail"
"strconv"
"strings"
"github.com/containers/ocicrypt/config"
"github.com/containers/ocicrypt/keywrap"
"github.com/pkg/errors"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet"
)
type gpgKeyWrapper struct {
}
// NewKeyWrapper returns a new key wrapping interface for pgp
func NewKeyWrapper() keywrap.KeyWrapper {
return &gpgKeyWrapper{}
}
var (
// GPGDefaultEncryptConfig is the default configuration for layer encryption/decryption
GPGDefaultEncryptConfig = &packet.Config{
Rand: rand.Reader,
DefaultHash: crypto.SHA256,
DefaultCipher: packet.CipherAES256,
CompressionConfig: &packet.CompressionConfig{Level: 0}, // No compression
RSABits: 2048,
}
)
func (kw *gpgKeyWrapper) GetAnnotationID() string {
return "org.opencontainers.image.enc.keys.pgp"
}
// WrapKeys wraps the session key for recpients and encrypts the optsData, which
// describe the symmetric key used for encrypting the layer
func (kw *gpgKeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
ciphertext := new(bytes.Buffer)
el, err := kw.createEntityList(ec)
if err != nil {
return nil, errors.Wrap(err, "unable to create entity list")
}
if len(el) == 0 {
// nothing to do -- not an error
return nil, nil
}
plaintextWriter, err := openpgp.Encrypt(ciphertext,
el, /*EntityList*/
nil, /* Sign*/
nil, /* FileHint */
GPGDefaultEncryptConfig)
if err != nil {
return nil, err
}
if _, err = plaintextWriter.Write(optsData); err != nil {
return nil, err
} else if err = plaintextWriter.Close(); err != nil {
return nil, err
}
return ciphertext.Bytes(), err
}
// UnwrapKey unwraps the symmetric key with which the layer is encrypted
// This symmetric key is encrypted in the PGP payload.
func (kw *gpgKeyWrapper) UnwrapKey(dc *config.DecryptConfig, pgpPacket []byte) ([]byte, error) {
pgpPrivateKeys, pgpPrivateKeysPwd, err := kw.getKeyParameters(dc.Parameters)
if err != nil {
return nil, err
}
for idx, pgpPrivateKey := range pgpPrivateKeys {
r := bytes.NewBuffer(pgpPrivateKey)
entityList, err := openpgp.ReadKeyRing(r)
if err != nil {
return nil, errors.Wrap(err, "unable to parse private keys")
}
var prompt openpgp.PromptFunction
if len(pgpPrivateKeysPwd) > idx {
responded := false
prompt = func(keys []openpgp.Key, symmetric bool) ([]byte, error) {
if responded {
return nil, fmt.Errorf("don't seem to have the right password")
}
responded = true
for _, key := range keys {
if key.PrivateKey != nil {
_ = key.PrivateKey.Decrypt(pgpPrivateKeysPwd[idx])
}
}
return pgpPrivateKeysPwd[idx], nil
}
}
r = bytes.NewBuffer(pgpPacket)
md, err := openpgp.ReadMessage(r, entityList, prompt, GPGDefaultEncryptConfig)
if err != nil {
continue
}
// we get the plain key options back
optsData, err := ioutil.ReadAll(md.UnverifiedBody)
if err != nil {
continue
}
return optsData, nil
}
return nil, errors.New("PGP: No suitable key found to unwrap key")
}
// GetKeyIdsFromWrappedKeys converts the base64 encoded PGPPacket to uint64 keyIds
func (kw *gpgKeyWrapper) GetKeyIdsFromPacket(b64pgpPackets string) ([]uint64, error) {
var keyids []uint64
for _, b64pgpPacket := range strings.Split(b64pgpPackets, ",") {
pgpPacket, err := base64.StdEncoding.DecodeString(b64pgpPacket)
if err != nil {
return nil, errors.Wrapf(err, "could not decode base64 encoded PGP packet")
}
newids, err := kw.getKeyIDs(pgpPacket)
if err != nil {
return nil, err
}
keyids = append(keyids, newids...)
}
return keyids, nil
}
// getKeyIDs parses a PGPPacket and gets the list of recipients' key IDs
func (kw *gpgKeyWrapper) getKeyIDs(pgpPacket []byte) ([]uint64, error) {
var keyids []uint64
kbuf := bytes.NewBuffer(pgpPacket)
packets := packet.NewReader(kbuf)
ParsePackets:
for {
p, err := packets.Next()
if err == io.EOF {
break ParsePackets
}
if err != nil {
return []uint64{}, errors.Wrapf(err, "packets.Next() failed")
}
switch p := p.(type) {
case *packet.EncryptedKey:
keyids = append(keyids, p.KeyId)
case *packet.SymmetricallyEncrypted:
break ParsePackets
}
}
return keyids, nil
}
// GetRecipients converts the wrappedKeys to an array of recipients
func (kw *gpgKeyWrapper) GetRecipients(b64pgpPackets string) ([]string, error) {
keyIds, err := kw.GetKeyIdsFromPacket(b64pgpPackets)
if err != nil {
return nil, err
}
var array []string
for _, keyid := range keyIds {
array = append(array, "0x"+strconv.FormatUint(keyid, 16))
}
return array, nil
}
func (kw *gpgKeyWrapper) GetPrivateKeys(dcparameters map[string][][]byte) [][]byte {
return dcparameters["gpg-privatekeys"]
}
func (kw *gpgKeyWrapper) getKeyParameters(dcparameters map[string][][]byte) ([][]byte, [][]byte, error) {
privKeys := kw.GetPrivateKeys(dcparameters)
if len(privKeys) == 0 {
return nil, nil, errors.New("GPG: Missing private key parameter")
}
return privKeys, dcparameters["gpg-privatekeys-passwords"], nil
}
// createEntityList creates the opengpg EntityList by reading the KeyRing
// first and then filtering out recipients' keys
func (kw *gpgKeyWrapper) createEntityList(ec *config.EncryptConfig) (openpgp.EntityList, error) {
pgpPubringFile := ec.Parameters["gpg-pubkeyringfile"]
if len(pgpPubringFile) == 0 {
return nil, nil
}
r := bytes.NewReader(pgpPubringFile[0])
entityList, err := openpgp.ReadKeyRing(r)
if err != nil {
return nil, err
}
gpgRecipients := ec.Parameters["gpg-recipients"]
if len(gpgRecipients) == 0 {
return nil, nil
}
rSet := make(map[string]int)
for _, r := range gpgRecipients {
rSet[string(r)] = 0
}
var filteredList openpgp.EntityList
for _, entity := range entityList {
for k := range entity.Identities {
addr, err := mail.ParseAddress(k)
if err != nil {
return nil, err
}
for _, r := range gpgRecipients {
recp := string(r)
if strings.Compare(addr.Name, recp) == 0 || strings.Compare(addr.Address, recp) == 0 {
filteredList = append(filteredList, entity)
rSet[recp] = rSet[recp] + 1
}
}
}
}
// make sure we found keys for all the Recipients...
var buffer bytes.Buffer
notFound := false
buffer.WriteString("PGP: No key found for the following recipients: ")
for k, v := range rSet {
if v == 0 {
if notFound {
buffer.WriteString(", ")
}
buffer.WriteString(k)
notFound = true
}
}
if notFound {
return nil, errors.New(buffer.String())
}
return filteredList, nil
}

View File

@@ -0,0 +1,132 @@
/*
Copyright The ocicrypt Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pkcs7
import (
"crypto"
"crypto/x509"
"github.com/containers/ocicrypt/config"
"github.com/containers/ocicrypt/keywrap"
"github.com/containers/ocicrypt/utils"
"github.com/fullsailor/pkcs7"
"github.com/pkg/errors"
)
type pkcs7KeyWrapper struct {
}
// NewKeyWrapper returns a new key wrapping interface using jwe
func NewKeyWrapper() keywrap.KeyWrapper {
return &pkcs7KeyWrapper{}
}
func (kw *pkcs7KeyWrapper) GetAnnotationID() string {
return "org.opencontainers.image.enc.keys.pkcs7"
}
// WrapKeys wraps the session key for recpients and encrypts the optsData, which
// describe the symmetric key used for encrypting the layer
func (kw *pkcs7KeyWrapper) WrapKeys(ec *config.EncryptConfig, optsData []byte) ([]byte, error) {
x509Certs, err := collectX509s(ec.Parameters["x509s"])
if err != nil {
return nil, err
}
// no recipients is not an error...
if len(x509Certs) == 0 {
return nil, nil
}
pkcs7.ContentEncryptionAlgorithm = pkcs7.EncryptionAlgorithmAES128GCM
return pkcs7.Encrypt(optsData, x509Certs)
}
func collectX509s(x509s [][]byte) ([]*x509.Certificate, error) {
if len(x509s) == 0 {
return nil, nil
}
var x509Certs []*x509.Certificate
for _, x509 := range x509s {
x509Cert, err := utils.ParseCertificate(x509, "PKCS7")
if err != nil {
return nil, err
}
x509Certs = append(x509Certs, x509Cert)
}
return x509Certs, nil
}
func (kw *pkcs7KeyWrapper) GetPrivateKeys(dcparameters map[string][][]byte) [][]byte {
return dcparameters["privkeys"]
}
func (kw *pkcs7KeyWrapper) getPrivateKeysPasswords(dcparameters map[string][][]byte) [][]byte {
return dcparameters["privkeys-passwords"]
}
// UnwrapKey unwraps the symmetric key with which the layer is encrypted
// This symmetric key is encrypted in the PKCS7 payload.
func (kw *pkcs7KeyWrapper) UnwrapKey(dc *config.DecryptConfig, pkcs7Packet []byte) ([]byte, error) {
privKeys := kw.GetPrivateKeys(dc.Parameters)
if len(privKeys) == 0 {
return nil, errors.New("no private keys found for PKCS7 decryption")
}
privKeysPasswords := kw.getPrivateKeysPasswords(dc.Parameters)
if len(privKeysPasswords) != len(privKeys) {
return nil, errors.New("private key password array length must be same as that of private keys")
}
x509Certs, err := collectX509s(dc.Parameters["x509s"])
if err != nil {
return nil, err
}
if len(x509Certs) == 0 {
return nil, errors.New("no x509 certificates found needed for PKCS7 decryption")
}
p7, err := pkcs7.Parse(pkcs7Packet)
if err != nil {
return nil, errors.Wrapf(err, "could not parse PKCS7 packet")
}
for idx, privKey := range privKeys {
key, err := utils.ParsePrivateKey(privKey, privKeysPasswords[idx], "PKCS7")
if err != nil {
return nil, err
}
for _, x509Cert := range x509Certs {
optsData, err := p7.Decrypt(x509Cert, crypto.PrivateKey(key))
if err != nil {
continue
}
return optsData, nil
}
}
return nil, errors.New("PKCS7: No suitable private key found for decryption")
}
// GetKeyIdsFromWrappedKeys converts the base64 encoded Packet to uint64 keyIds;
// We cannot do this with pkcs7
func (kw *pkcs7KeyWrapper) GetKeyIdsFromPacket(b64pkcs7Packets string) ([]uint64, error) {
return nil, nil
}
// GetRecipients converts the wrappedKeys to an array of recipients
// We cannot do this with pkcs7
func (kw *pkcs7KeyWrapper) GetRecipients(b64pkcs7Packets string) ([]string, error) {
return []string{"[pkcs7]"}, nil
}