Files
moby/vendor/github.com/docker/swarmkit/ca/keyutils/keyutils.go
Sebastiaan van Stijn 27749659d5 Bump SwarmKit to 831df679a0b8a21b4dccd5791667d030642de7ff
Changes included:

- Ingress network should not be attachable
- [manager/state] Add fernet as an option for raft encryption
- Log GRPC server errors
- Log leadership changes at manager level
- [state/raft] Increase raft ElectionTick to 10xHeartbeatTick
- Remove the containerd executor
- agent: backoff session when no remotes are available
- [ca/manager] Remove root CA key encryption support entirely
- Fix agent logging race (fixes https://github.com/docker/swarmkit/issues/2576)
- Adding logic to restore networks in order

Also adds github.com/fernet/fernet-go as a new dependency

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-04-02 15:17:38 -07:00

85 lines
2.7 KiB
Go

// Package keyutils serves as a utility to parse, encrypt and decrypt
// PKCS#1 and PKCS#8 private keys based on current FIPS mode status,
// supporting only EC type keys. It always allows PKCS#8 private keys
// and disallow PKCS#1 private keys in FIPS-mode.
package keyutils
import (
"crypto"
cryptorand "crypto/rand"
"crypto/x509"
"encoding/pem"
"errors"
"github.com/cloudflare/cfssl/helpers"
"github.com/docker/swarmkit/ca/pkcs8"
"github.com/docker/swarmkit/fips"
)
var errFIPSUnsupportedKeyFormat = errors.New("unsupported key format due to FIPS compliance")
// IsPKCS8 returns true if the provided der bytes is encrypted/unencrypted PKCS#8 key
func IsPKCS8(derBytes []byte) bool {
if _, err := x509.ParsePKCS8PrivateKey(derBytes); err == nil {
return true
}
return pkcs8.IsEncryptedPEMBlock(&pem.Block{
Type: "PRIVATE KEY",
Headers: nil,
Bytes: derBytes,
})
}
// ParsePrivateKeyPEMWithPassword parses an encrypted or a decrypted PKCS#1 or PKCS#8 PEM to crypto.Signer.
// It returns an error in FIPS mode if PKCS#1 PEM bytes are passed.
func ParsePrivateKeyPEMWithPassword(pemBytes, password []byte) (crypto.Signer, error) {
block, _ := pem.Decode(pemBytes)
if block == nil {
return nil, errors.New("Could not parse PEM")
}
if IsPKCS8(block.Bytes) {
return pkcs8.ParsePrivateKeyPEMWithPassword(pemBytes, password)
} else if fips.Enabled() {
return nil, errFIPSUnsupportedKeyFormat
}
return helpers.ParsePrivateKeyPEMWithPassword(pemBytes, password)
}
// IsEncryptedPEMBlock checks if a PKCS#1 or PKCS#8 PEM-block is encrypted or not
// It returns false in FIPS mode even if PKCS#1 is encrypted
func IsEncryptedPEMBlock(block *pem.Block) bool {
return pkcs8.IsEncryptedPEMBlock(block) || (!fips.Enabled() && x509.IsEncryptedPEMBlock(block))
}
// DecryptPEMBlock requires PKCS#1 or PKCS#8 PEM Block and password to decrypt and return unencrypted der []byte
// It returns an error in FIPS mode when PKCS#1 PEM Block is passed.
func DecryptPEMBlock(block *pem.Block, password []byte) ([]byte, error) {
if IsPKCS8(block.Bytes) {
return pkcs8.DecryptPEMBlock(block, password)
} else if fips.Enabled() {
return nil, errFIPSUnsupportedKeyFormat
}
return x509.DecryptPEMBlock(block, password)
}
// EncryptPEMBlock takes DER-format bytes and password to return an encrypted PKCS#1 or PKCS#8 PEM-block
// It returns an error in FIPS mode when PKCS#1 PEM bytes are passed.
func EncryptPEMBlock(data, password []byte) (*pem.Block, error) {
if IsPKCS8(data) {
return pkcs8.EncryptPEMBlock(data, password)
} else if fips.Enabled() {
return nil, errFIPSUnsupportedKeyFormat
}
cipherType := x509.PEMCipherAES256
return x509.EncryptPEMBlock(cryptorand.Reader,
"EC PRIVATE KEY",
data,
password,
cipherType)
}