mirror of
https://github.com/containers/podman.git
synced 2025-12-13 02:09:16 +08:00
Bump github.com/containers/ocicrypt from 1.0.3 to 1.1.0
Bumps [github.com/containers/ocicrypt](https://github.com/containers/ocicrypt) from 1.0.3 to 1.1.0. - [Release notes](https://github.com/containers/ocicrypt/releases) - [Commits](https://github.com/containers/ocicrypt/compare/v1.0.3...v1.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:
committed by
Daniel J Walsh
parent
19507d0ffe
commit
08d8290f1d
134
vendor/github.com/containers/ocicrypt/crypto/pkcs11/common.go
generated
vendored
Normal file
134
vendor/github.com/containers/ocicrypt/crypto/pkcs11/common.go
generated
vendored
Normal 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
|
||||
}
|
||||
487
vendor/github.com/containers/ocicrypt/crypto/pkcs11/pkcs11helpers.go
generated
vendored
Normal file
487
vendor/github.com/containers/ocicrypt/crypto/pkcs11/pkcs11helpers.go
generated
vendored
Normal 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)
|
||||
}
|
||||
31
vendor/github.com/containers/ocicrypt/crypto/pkcs11/pkcs11helpers_nocgo.go
generated
vendored
Normal file
31
vendor/github.com/containers/ocicrypt/crypto/pkcs11/pkcs11helpers_nocgo.go
generated
vendored
Normal 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")
|
||||
}
|
||||
114
vendor/github.com/containers/ocicrypt/crypto/pkcs11/utils.go
generated
vendored
Normal file
114
vendor/github.com/containers/ocicrypt/crypto/pkcs11/utils.go
generated
vendored
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user