github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/crypto/tls/tls.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package tls partially implements TLS 1.2, as specified in RFC 5246.
     6  package tls
     7  
     8  import (
     9  	"crypto"
    10  	"crypto/ecdsa"
    11  	"crypto/rsa"
    12  	"crypto/x509"
    13  	"encoding/pem"
    14  	"errors"
    15  	"io/ioutil"
    16  	"net"
    17  	"strings"
    18  )
    19  
    20  // Server returns a new TLS server side connection
    21  // using conn as the underlying transport.
    22  // The configuration config must be non-nil and must have
    23  // at least one certificate.
    24  func Server(conn net.Conn, config *Config) *Conn {
    25  	return &Conn{conn: conn, config: config}
    26  }
    27  
    28  // Client returns a new TLS client side connection
    29  // using conn as the underlying transport.
    30  // Client interprets a nil configuration as equivalent to
    31  // the zero configuration; see the documentation of Config
    32  // for the defaults.
    33  func Client(conn net.Conn, config *Config) *Conn {
    34  	return &Conn{conn: conn, config: config, isClient: true}
    35  }
    36  
    37  // A listener implements a network listener (net.Listener) for TLS connections.
    38  type listener struct {
    39  	net.Listener
    40  	config *Config
    41  }
    42  
    43  // Accept waits for and returns the next incoming TLS connection.
    44  // The returned connection c is a *tls.Conn.
    45  func (l *listener) Accept() (c net.Conn, err error) {
    46  	c, err = l.Listener.Accept()
    47  	if err != nil {
    48  		return
    49  	}
    50  	c = Server(c, l.config)
    51  	return
    52  }
    53  
    54  // NewListener creates a Listener which accepts connections from an inner
    55  // Listener and wraps each connection with Server.
    56  // The configuration config must be non-nil and must have
    57  // at least one certificate.
    58  func NewListener(inner net.Listener, config *Config) net.Listener {
    59  	l := new(listener)
    60  	l.Listener = inner
    61  	l.config = config
    62  	return l
    63  }
    64  
    65  // Listen creates a TLS listener accepting connections on the
    66  // given network address using net.Listen.
    67  // The configuration config must be non-nil and must have
    68  // at least one certificate.
    69  func Listen(network, laddr string, config *Config) (net.Listener, error) {
    70  	if config == nil || len(config.Certificates) == 0 {
    71  		return nil, errors.New("tls.Listen: no certificates in configuration")
    72  	}
    73  	l, err := net.Listen(network, laddr)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	return NewListener(l, config), nil
    78  }
    79  
    80  // Dial connects to the given network address using net.Dial
    81  // and then initiates a TLS handshake, returning the resulting
    82  // TLS connection.
    83  // Dial interprets a nil configuration as equivalent to
    84  // the zero configuration; see the documentation of Config
    85  // for the defaults.
    86  func Dial(network, addr string, config *Config) (*Conn, error) {
    87  	raddr := addr
    88  	c, err := net.Dial(network, raddr)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	colonPos := strings.LastIndex(raddr, ":")
    94  	if colonPos == -1 {
    95  		colonPos = len(raddr)
    96  	}
    97  	hostname := raddr[:colonPos]
    98  
    99  	if config == nil {
   100  		config = defaultConfig()
   101  	}
   102  	// If no ServerName is set, infer the ServerName
   103  	// from the hostname we're connecting to.
   104  	if config.ServerName == "" {
   105  		// Make a copy to avoid polluting argument or default.
   106  		c := *config
   107  		c.ServerName = hostname
   108  		config = &c
   109  	}
   110  	conn := Client(c, config)
   111  	if err = conn.Handshake(); err != nil {
   112  		c.Close()
   113  		return nil, err
   114  	}
   115  	return conn, nil
   116  }
   117  
   118  // LoadX509KeyPair reads and parses a public/private key pair from a pair of
   119  // files. The files must contain PEM encoded data.
   120  func LoadX509KeyPair(certFile, keyFile string) (cert Certificate, err error) {
   121  	certPEMBlock, err := ioutil.ReadFile(certFile)
   122  	if err != nil {
   123  		return
   124  	}
   125  	keyPEMBlock, err := ioutil.ReadFile(keyFile)
   126  	if err != nil {
   127  		return
   128  	}
   129  	return X509KeyPair(certPEMBlock, keyPEMBlock)
   130  }
   131  
   132  // X509KeyPair parses a public/private key pair from a pair of
   133  // PEM encoded data.
   134  func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error) {
   135  	var certDERBlock *pem.Block
   136  	for {
   137  		certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
   138  		if certDERBlock == nil {
   139  			break
   140  		}
   141  		if certDERBlock.Type == "CERTIFICATE" {
   142  			cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
   143  		}
   144  	}
   145  
   146  	if len(cert.Certificate) == 0 {
   147  		err = errors.New("crypto/tls: failed to parse certificate PEM data")
   148  		return
   149  	}
   150  
   151  	var keyDERBlock *pem.Block
   152  	for {
   153  		keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
   154  		if keyDERBlock == nil {
   155  			err = errors.New("crypto/tls: failed to parse key PEM data")
   156  			return
   157  		}
   158  		if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
   159  			break
   160  		}
   161  	}
   162  
   163  	cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
   164  	if err != nil {
   165  		return
   166  	}
   167  
   168  	// We don't need to parse the public key for TLS, but we so do anyway
   169  	// to check that it looks sane and matches the private key.
   170  	x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
   171  	if err != nil {
   172  		return
   173  	}
   174  
   175  	switch pub := x509Cert.PublicKey.(type) {
   176  	case *rsa.PublicKey:
   177  		priv, ok := cert.PrivateKey.(*rsa.PrivateKey)
   178  		if !ok {
   179  			err = errors.New("crypto/tls: private key type does not match public key type")
   180  			return
   181  		}
   182  		if pub.N.Cmp(priv.N) != 0 {
   183  			err = errors.New("crypto/tls: private key does not match public key")
   184  			return
   185  		}
   186  	case *ecdsa.PublicKey:
   187  		priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
   188  		if !ok {
   189  			err = errors.New("crypto/tls: private key type does not match public key type")
   190  			return
   191  
   192  		}
   193  		if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
   194  			err = errors.New("crypto/tls: private key does not match public key")
   195  			return
   196  		}
   197  	default:
   198  		err = errors.New("crypto/tls: unknown public key algorithm")
   199  		return
   200  	}
   201  
   202  	return
   203  }
   204  
   205  // Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
   206  // PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
   207  // OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
   208  func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
   209  	if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
   210  		return key, nil
   211  	}
   212  	if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
   213  		switch key := key.(type) {
   214  		case *rsa.PrivateKey, *ecdsa.PrivateKey:
   215  			return key, nil
   216  		default:
   217  			return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping")
   218  		}
   219  	}
   220  	if key, err := x509.ParseECPrivateKey(der); err == nil {
   221  		return key, nil
   222  	}
   223  
   224  	return nil, errors.New("crypto/tls: failed to parse private key")
   225  }