From 7180f887ea4204a4a99f0de85ada64cac15856d7 Mon Sep 17 00:00:00 2001 From: Arash Deshmeh Date: Wed, 5 Apr 2017 12:21:40 -0400 Subject: [PATCH] vendor docker/go-connections to include the enhacement for decrypting keys Signed-off-by: Arash Deshmeh --- vendor.conf | 2 +- .../docker/go-connections/tlsconfig/config.go | 76 +++++++++++++++++-- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/vendor.conf b/vendor.conf index 29db3350c1..6cab21fc74 100644 --- a/vendor.conf +++ b/vendor.conf @@ -17,7 +17,7 @@ github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 golang.org/x/net c427ad74c6d7a814201695e9ffde0c5d400a7674 golang.org/x/sys 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9 github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1 -github.com/docker/go-connections a2afab9802043837035592f1c24827fb70766de9 +github.com/docker/go-connections e15c02316c12de00874640cd76311849de2aeed5 golang.org/x/text f72d8390a633d5dfb0cc84043294db9f6c935756 github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 diff --git a/vendor/github.com/docker/go-connections/tlsconfig/config.go b/vendor/github.com/docker/go-connections/tlsconfig/config.go index 0f8684497e..ad4b112ab3 100644 --- a/vendor/github.com/docker/go-connections/tlsconfig/config.go +++ b/vendor/github.com/docker/go-connections/tlsconfig/config.go @@ -8,11 +8,13 @@ package tlsconfig import ( "crypto/tls" "crypto/x509" + "encoding/pem" "fmt" "io/ioutil" "os" "github.com/Sirupsen/logrus" + "github.com/pkg/errors" ) // Options represents the information needed to create client and server TLS configurations. @@ -34,6 +36,9 @@ type Options struct { // the system pool will be used. ExclusiveRootPools bool MinVersion uint16 + // If Passphrase is set, it will be used to decrypt a TLS private key + // if the key is encrypted + Passphrase string } // Extra (server-side) accepted CBC cipher suites - will phase out in the future @@ -127,6 +132,67 @@ func adjustMinVersion(options Options, config *tls.Config) error { return nil } +// IsErrEncryptedKey returns true if the 'err' is an error of incorrect +// password when tryin to decrypt a TLS private key +func IsErrEncryptedKey(err error) bool { + return errors.Cause(err) == x509.IncorrectPasswordError +} + +// getPrivateKey returns the private key in 'keyBytes', in PEM-encoded format. +// If the private key is encrypted, 'passphrase' is used to decrypted the +// private key. +func getPrivateKey(keyBytes []byte, passphrase string) ([]byte, error) { + // this section makes some small changes to code from notary/tuf/utils/x509.go + pemBlock, _ := pem.Decode(keyBytes) + if pemBlock == nil { + return nil, fmt.Errorf("no valid private key found") + } + + var err error + if x509.IsEncryptedPEMBlock(pemBlock) { + keyBytes, err = x509.DecryptPEMBlock(pemBlock, []byte(passphrase)) + if err != nil { + return nil, errors.Wrap(err, "private key is encrypted, but could not decrypt it") + } + keyBytes = pem.EncodeToMemory(&pem.Block{Type: pemBlock.Type, Bytes: keyBytes}) + } + + return keyBytes, nil +} + +// getCert returns a Certificate from the CertFile and KeyFile in 'options', +// if the key is encrypted, the Passphrase in 'options' will be used to +// decrypt it. +func getCert(options Options) ([]tls.Certificate, error) { + if options.CertFile == "" && options.KeyFile == "" { + return nil, nil + } + + errMessage := "Could not load X509 key pair" + + cert, err := ioutil.ReadFile(options.CertFile) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + + prKeyBytes, err := ioutil.ReadFile(options.KeyFile) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + + prKeyBytes, err = getPrivateKey(prKeyBytes, options.Passphrase) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + + tlsCert, err := tls.X509KeyPair(cert, prKeyBytes) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + + return []tls.Certificate{tlsCert}, nil +} + // Client returns a TLS configuration meant to be used by a client. func Client(options Options) (*tls.Config, error) { tlsConfig := ClientDefault() @@ -139,13 +205,11 @@ func Client(options Options) (*tls.Config, error) { tlsConfig.RootCAs = CAs } - if options.CertFile != "" || options.KeyFile != "" { - tlsCert, err := tls.LoadX509KeyPair(options.CertFile, options.KeyFile) - if err != nil { - return nil, fmt.Errorf("Could not load X509 key pair: %v. Make sure the key is not encrypted", err) - } - tlsConfig.Certificates = []tls.Certificate{tlsCert} + tlsCerts, err := getCert(options) + if err != nil { + return nil, err } + tlsConfig.Certificates = tlsCerts if err := adjustMinVersion(options, tlsConfig); err != nil { return nil, err