blob: 40156a0013bc9fb982d2cd143d57c2759232f6e7 [file] [log] [blame]
Adam Langley950f2632009-11-05 16:43:29 -08001// 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
Frithjof Schulze4d7c6352013-10-02 12:09:13 -04005// Package tls partially implements TLS 1.2, as specified in RFC 5246.
Adam Langley950f2632009-11-05 16:43:29 -08006package tls
7
8import (
Joel Singaaf3b712012-11-16 19:33:59 +11009 "crypto"
10 "crypto/ecdsa"
Adam Langley836529a2010-11-05 09:54:56 -040011 "crypto/rsa"
12 "crypto/x509"
13 "encoding/pem"
Russ Coxc2049d22011-11-01 22:04:37 -040014 "errors"
Adam Langleyfc23def2010-07-02 13:00:18 -040015 "io/ioutil"
Robert Griesemer5a1d3322009-12-15 15:33:31 -080016 "net"
Adam Langley836529a2010-11-05 09:54:56 -040017 "strings"
Adam Langley950f2632009-11-05 16:43:29 -080018)
19
Russ Coxb15c4242010-12-07 16:15:15 -050020// 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.
Adam Langley6e0842d2009-11-21 15:53:03 -080024func Server(conn net.Conn, config *Config) *Conn {
Russ Cox72d93222010-04-26 22:19:04 -070025 return &Conn{conn: conn, config: config}
Adam Langley6e0842d2009-11-21 15:53:03 -080026}
27
Russ Coxb15c4242010-12-07 16:15:15 -050028// Client returns a new TLS client side connection
29// using conn as the underlying transport.
Adam Langley80692a32014-02-19 11:17:09 -050030// The config cannot be nil: users must set either ServerHostname or
31// InsecureSkipVerify in the config.
Adam Langley6e0842d2009-11-21 15:53:03 -080032func Client(conn net.Conn, config *Config) *Conn {
Russ Cox72d93222010-04-26 22:19:04 -070033 return &Conn{conn: conn, config: config, isClient: true}
Adam Langley6e0842d2009-11-21 15:53:03 -080034}
35
Adam Langley005686f2012-02-03 15:08:53 -050036// A listener implements a network listener (net.Listener) for TLS connections.
37type listener struct {
38 net.Listener
39 config *Config
Adam Langley950f2632009-11-05 16:43:29 -080040}
41
Russ Coxb15c4242010-12-07 16:15:15 -050042// Accept waits for and returns the next incoming TLS connection.
43// The returned connection c is a *tls.Conn.
Adam Langley005686f2012-02-03 15:08:53 -050044func (l *listener) Accept() (c net.Conn, err error) {
45 c, err = l.Listener.Accept()
Adam Langley950f2632009-11-05 16:43:29 -080046 if err != nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080047 return
Adam Langley950f2632009-11-05 16:43:29 -080048 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -080049 c = Server(c, l.config)
50 return
Adam Langley950f2632009-11-05 16:43:29 -080051}
52
Adam Langley950f2632009-11-05 16:43:29 -080053// NewListener creates a Listener which accepts connections from an inner
54// Listener and wraps each connection with Server.
Russ Cox72d93222010-04-26 22:19:04 -070055// The configuration config must be non-nil and must have
56// at least one certificate.
Adam Langley005686f2012-02-03 15:08:53 -050057func NewListener(inner net.Listener, config *Config) net.Listener {
58 l := new(listener)
59 l.Listener = inner
Robert Griesemer5a1d3322009-12-15 15:33:31 -080060 l.config = config
Adam Langley005686f2012-02-03 15:08:53 -050061 return l
Adam Langley950f2632009-11-05 16:43:29 -080062}
Russ Cox99d258a2010-04-05 14:38:02 -070063
Russ Coxb15c4242010-12-07 16:15:15 -050064// Listen creates a TLS listener accepting connections on the
65// given network address using net.Listen.
66// The configuration config must be non-nil and must have
67// at least one certificate.
Adam Langley005686f2012-02-03 15:08:53 -050068func Listen(network, laddr string, config *Config) (net.Listener, error) {
Russ Cox72d93222010-04-26 22:19:04 -070069 if config == nil || len(config.Certificates) == 0 {
Russ Coxc2049d22011-11-01 22:04:37 -040070 return nil, errors.New("tls.Listen: no certificates in configuration")
Russ Cox72d93222010-04-26 22:19:04 -070071 }
Russ Cox99d258a2010-04-05 14:38:02 -070072 l, err := net.Listen(network, laddr)
73 if err != nil {
74 return nil, err
75 }
Russ Cox72d93222010-04-26 22:19:04 -070076 return NewListener(l, config), nil
Russ Cox99d258a2010-04-05 14:38:02 -070077}
78
Russ Coxb15c4242010-12-07 16:15:15 -050079// Dial connects to the given network address using net.Dial
80// and then initiates a TLS handshake, returning the resulting
81// TLS connection.
82// Dial interprets a nil configuration as equivalent to
83// the zero configuration; see the documentation of Config
84// for the defaults.
Russ Coxc2049d22011-11-01 22:04:37 -040085func Dial(network, addr string, config *Config) (*Conn, error) {
Russ Cox41f93a42011-03-28 23:28:42 -040086 raddr := addr
87 c, err := net.Dial(network, raddr)
Russ Cox99d258a2010-04-05 14:38:02 -070088 if err != nil {
89 return nil, err
90 }
Adam Langley836529a2010-11-05 09:54:56 -040091
92 colonPos := strings.LastIndex(raddr, ":")
93 if colonPos == -1 {
94 colonPos = len(raddr)
95 }
96 hostname := raddr[:colonPos]
97
Russ Coxb15c4242010-12-07 16:15:15 -050098 if config == nil {
99 config = defaultConfig()
Adam Langley6989f6e2010-09-20 10:32:08 -0400100 }
Mikkel Krautza324a5a2012-03-07 13:12:35 -0500101 // If no ServerName is set, infer the ServerName
102 // from the hostname we're connecting to.
103 if config.ServerName == "" {
Russ Coxb15c4242010-12-07 16:15:15 -0500104 // Make a copy to avoid polluting argument or default.
105 c := *config
106 c.ServerName = hostname
107 config = &c
108 }
109 conn := Client(c, config)
110 if err = conn.Handshake(); err != nil {
111 c.Close()
112 return nil, err
113 }
114 return conn, nil
Russ Cox99d258a2010-04-05 14:38:02 -0700115}
Adam Langleyfc23def2010-07-02 13:00:18 -0400116
Adam Langleyf6e2eab2010-10-11 10:39:56 -0400117// LoadX509KeyPair reads and parses a public/private key pair from a pair of
118// files. The files must contain PEM encoded data.
Jeff R. Allenc581ec42012-01-05 12:05:38 -0500119func LoadX509KeyPair(certFile, keyFile string) (cert Certificate, err error) {
Adam Langleyfc23def2010-07-02 13:00:18 -0400120 certPEMBlock, err := ioutil.ReadFile(certFile)
121 if err != nil {
122 return
123 }
Brad Fitzpatrickcc408702011-04-04 08:32:59 -0700124 keyPEMBlock, err := ioutil.ReadFile(keyFile)
125 if err != nil {
126 return
127 }
128 return X509KeyPair(certPEMBlock, keyPEMBlock)
129}
Adam Langleyfc23def2010-07-02 13:00:18 -0400130
Brad Fitzpatrickcc408702011-04-04 08:32:59 -0700131// X509KeyPair parses a public/private key pair from a pair of
132// PEM encoded data.
Russ Coxc2049d22011-11-01 22:04:37 -0400133func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err error) {
Adam Langley5626bd92011-02-05 13:54:25 -0500134 var certDERBlock *pem.Block
135 for {
136 certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
137 if certDERBlock == nil {
138 break
139 }
140 if certDERBlock.Type == "CERTIFICATE" {
141 cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
142 }
143 }
144
145 if len(cert.Certificate) == 0 {
Russ Coxc2049d22011-11-01 22:04:37 -0400146 err = errors.New("crypto/tls: failed to parse certificate PEM data")
Adam Langleyfc23def2010-07-02 13:00:18 -0400147 return
148 }
149
Adam Langleyecc04b82012-09-13 11:00:16 -0400150 var keyDERBlock *pem.Block
151 for {
152 keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
153 if keyDERBlock == nil {
154 err = errors.New("crypto/tls: failed to parse key PEM data")
155 return
156 }
Brad Fitzpatrick444b7b52012-12-01 11:02:08 -0800157 if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
Adam Langleyecc04b82012-09-13 11:00:16 -0400158 break
159 }
Adam Langleyfc23def2010-07-02 13:00:18 -0400160 }
161
Joel Singaaf3b712012-11-16 19:33:59 +1100162 cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
163 if err != nil {
164 return
Adam Langleyfc23def2010-07-02 13:00:18 -0400165 }
166
Adam Langleyfc23def2010-07-02 13:00:18 -0400167 // We don't need to parse the public key for TLS, but we so do anyway
168 // to check that it looks sane and matches the private key.
Adam Langley5626bd92011-02-05 13:54:25 -0500169 x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
Adam Langleyfc23def2010-07-02 13:00:18 -0400170 if err != nil {
171 return
172 }
173
Joel Singaaf3b712012-11-16 19:33:59 +1100174 switch pub := x509Cert.PublicKey.(type) {
175 case *rsa.PublicKey:
176 priv, ok := cert.PrivateKey.(*rsa.PrivateKey)
177 if !ok {
178 err = errors.New("crypto/tls: private key type does not match public key type")
179 return
180 }
181 if pub.N.Cmp(priv.N) != 0 {
182 err = errors.New("crypto/tls: private key does not match public key")
183 return
184 }
185 case *ecdsa.PublicKey:
186 priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
187 if !ok {
188 err = errors.New("crypto/tls: private key type does not match public key type")
189 return
190
191 }
192 if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
193 err = errors.New("crypto/tls: private key does not match public key")
194 return
195 }
196 default:
197 err = errors.New("crypto/tls: unknown public key algorithm")
Adam Langleyfc23def2010-07-02 13:00:18 -0400198 return
199 }
200
201 return
202}
Joel Singaaf3b712012-11-16 19:33:59 +1100203
204// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
205// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
206// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
207func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
208 if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
209 return key, nil
210 }
211 if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
212 switch key := key.(type) {
213 case *rsa.PrivateKey, *ecdsa.PrivateKey:
214 return key, nil
215 default:
216 return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping")
217 }
218 }
219 if key, err := x509.ParseECPrivateKey(der); err == nil {
220 return key, nil
221 }
222
223 return nil, errors.New("crypto/tls: failed to parse private key")
224}