aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/crypto/tls/tls.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/crypto/tls/tls.go')
-rw-r--r--libgo/go/crypto/tls/tls.go55
1 files changed, 41 insertions, 14 deletions
diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go
index 0b1c3778ad4..4bedd7682d3 100644
--- a/libgo/go/crypto/tls/tls.go
+++ b/libgo/go/crypto/tls/tls.go
@@ -5,6 +5,11 @@
// Package tls partially implements TLS 1.2, as specified in RFC 5246.
package tls
+// BUG(agl): The crypto/tls package does not implement countermeasures
+// against Lucky13 attacks on CBC-mode encryption. See
+// http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and
+// https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
+
import (
"crypto"
"crypto/ecdsa"
@@ -12,6 +17,7 @@ import (
"crypto/x509"
"encoding/pem"
"errors"
+ "fmt"
"io/ioutil"
"net"
"strings"
@@ -20,8 +26,8 @@ import (
// Server returns a new TLS server side connection
// using conn as the underlying transport.
-// The configuration config must be non-nil and must have
-// at least one certificate.
+// The configuration config must be non-nil and must include
+// at least one certificate or else set GetCertificate.
func Server(conn net.Conn, config *Config) *Conn {
return &Conn{conn: conn, config: config}
}
@@ -53,8 +59,8 @@ func (l *listener) Accept() (c net.Conn, err error) {
// NewListener creates a Listener which accepts connections from an inner
// Listener and wraps each connection with Server.
-// The configuration config must be non-nil and must have
-// at least one certificate.
+// The configuration config must be non-nil and must include
+// at least one certificate or else set GetCertificate.
func NewListener(inner net.Listener, config *Config) net.Listener {
l := new(listener)
l.Listener = inner
@@ -64,11 +70,11 @@ func NewListener(inner net.Listener, config *Config) net.Listener {
// Listen creates a TLS listener accepting connections on the
// given network address using net.Listen.
-// The configuration config must be non-nil and must have
-// at least one certificate.
+// The configuration config must be non-nil and must include
+// at least one certificate or else set GetCertificate.
func Listen(network, laddr string, config *Config) (net.Listener, error) {
- if config == nil || len(config.Certificates) == 0 {
- return nil, errors.New("tls.Listen: no certificates in configuration")
+ if config == nil || (len(config.Certificates) == 0 && config.GetCertificate == nil) {
+ return nil, errors.New("tls: neither Certificates nor GetCertificate set in Config")
}
l, err := net.Listen(network, laddr)
if err != nil {
@@ -166,7 +172,9 @@ func Dial(network, addr string, config *Config) (*Conn, error) {
}
// LoadX509KeyPair reads and parses a public/private key pair from a pair of
-// files. The files must contain PEM encoded data.
+// files. The files must contain PEM encoded data. On successful return,
+// Certificate.Leaf will be nil because the parsed form of the certificate is
+// not retained.
func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) {
certPEMBlock, err := ioutil.ReadFile(certFile)
if err != nil {
@@ -180,34 +188,53 @@ func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) {
}
// X509KeyPair parses a public/private key pair from a pair of
-// PEM encoded data.
+// PEM encoded data. On successful return, Certificate.Leaf will be nil because
+// the parsed form of the certificate is not retained.
func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) {
- var cert Certificate
- var certDERBlock *pem.Block
fail := func(err error) (Certificate, error) { return Certificate{}, err }
+
+ var cert Certificate
+ var skippedBlockTypes []string
for {
+ var certDERBlock *pem.Block
certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
if certDERBlock == nil {
break
}
if certDERBlock.Type == "CERTIFICATE" {
cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
+ } else {
+ skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type)
}
}
if len(cert.Certificate) == 0 {
- return fail(errors.New("crypto/tls: failed to parse certificate PEM data"))
+ if len(skippedBlockTypes) == 0 {
+ return fail(errors.New("crypto/tls: failed to find any PEM data in certificate input"))
+ } else if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") {
+ return fail(errors.New("crypto/tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched"))
+ } else {
+ return fail(fmt.Errorf("crypto/tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes))
+ }
}
+ skippedBlockTypes = skippedBlockTypes[:0]
var keyDERBlock *pem.Block
for {
keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
if keyDERBlock == nil {
- return fail(errors.New("crypto/tls: failed to parse key PEM data"))
+ if len(skippedBlockTypes) == 0 {
+ return fail(errors.New("crypto/tls: failed to find any PEM data in key input"))
+ } else if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" {
+ return fail(errors.New("crypto/tls: found a certificate rather than a key in the PEM for the private key"))
+ } else {
+ return fail(fmt.Errorf("crypto/tls: failed to find PEM block with type ending in \"PRIVATE KEY\" in key input after skipping PEM blocks of the following types: %v", skippedBlockTypes))
+ }
}
if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
break
}
+ skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type)
}
var err error