Adam Langley | 950f263 | 2009-11-05 16:43:29 -0800 | [diff] [blame] | 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 | |
Frithjof Schulze | 4d7c635 | 2013-10-02 12:09:13 -0400 | [diff] [blame] | 5 | // Package tls partially implements TLS 1.2, as specified in RFC 5246. |
Adam Langley | 950f263 | 2009-11-05 16:43:29 -0800 | [diff] [blame] | 6 | package tls |
| 7 | |
Brad Fitzpatrick | 91abab0 | 2015-12-08 16:49:17 +0000 | [diff] [blame] | 8 | // BUG(agl): The crypto/tls package does not implement countermeasures |
| 9 | // against Lucky13 attacks on CBC-mode encryption. See |
| 10 | // http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and |
| 11 | // https://www.imperialviolet.org/2013/02/04/luckythirteen.html. |
| 12 | |
Adam Langley | 950f263 | 2009-11-05 16:43:29 -0800 | [diff] [blame] | 13 | import ( |
Joel Sing | aaf3b71 | 2012-11-16 19:33:59 +1100 | [diff] [blame] | 14 | "crypto" |
| 15 | "crypto/ecdsa" |
Adam Langley | 836529a | 2010-11-05 09:54:56 -0400 | [diff] [blame] | 16 | "crypto/rsa" |
| 17 | "crypto/x509" |
| 18 | "encoding/pem" |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame] | 19 | "errors" |
Adam Langley | be16001 | 2015-08-30 10:23:30 -0700 | [diff] [blame] | 20 | "fmt" |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 21 | "io/ioutil" |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 22 | "net" |
Adam Langley | 836529a | 2010-11-05 09:54:56 -0400 | [diff] [blame] | 23 | "strings" |
Adam Langley | 1f8b2a6 | 2014-02-28 09:40:12 -0500 | [diff] [blame] | 24 | "time" |
Adam Langley | 950f263 | 2009-11-05 16:43:29 -0800 | [diff] [blame] | 25 | ) |
| 26 | |
Russ Cox | b15c424 | 2010-12-07 16:15:15 -0500 | [diff] [blame] | 27 | // Server returns a new TLS server side connection |
| 28 | // using conn as the underlying transport. |
aubble | 34695c4 | 2015-08-20 14:26:56 -0400 | [diff] [blame] | 29 | // The configuration config must be non-nil and must include |
| 30 | // at least one certificate or else set GetCertificate. |
Adam Langley | 6e0842d | 2009-11-21 15:53:03 -0800 | [diff] [blame] | 31 | func Server(conn net.Conn, config *Config) *Conn { |
Russ Cox | 72d9322 | 2010-04-26 22:19:04 -0700 | [diff] [blame] | 32 | return &Conn{conn: conn, config: config} |
Adam Langley | 6e0842d | 2009-11-21 15:53:03 -0800 | [diff] [blame] | 33 | } |
| 34 | |
Russ Cox | b15c424 | 2010-12-07 16:15:15 -0500 | [diff] [blame] | 35 | // Client returns a new TLS client side connection |
| 36 | // using conn as the underlying transport. |
Brad Fitzpatrick | 19fe9a2 | 2014-06-03 18:11:17 +1000 | [diff] [blame] | 37 | // The config cannot be nil: users must set either ServerName or |
Adam Langley | 80692a3 | 2014-02-19 11:17:09 -0500 | [diff] [blame] | 38 | // InsecureSkipVerify in the config. |
Adam Langley | 6e0842d | 2009-11-21 15:53:03 -0800 | [diff] [blame] | 39 | func Client(conn net.Conn, config *Config) *Conn { |
Russ Cox | 72d9322 | 2010-04-26 22:19:04 -0700 | [diff] [blame] | 40 | return &Conn{conn: conn, config: config, isClient: true} |
Adam Langley | 6e0842d | 2009-11-21 15:53:03 -0800 | [diff] [blame] | 41 | } |
| 42 | |
Adam Langley | 005686f | 2012-02-03 15:08:53 -0500 | [diff] [blame] | 43 | // A listener implements a network listener (net.Listener) for TLS connections. |
| 44 | type listener struct { |
| 45 | net.Listener |
| 46 | config *Config |
Adam Langley | 950f263 | 2009-11-05 16:43:29 -0800 | [diff] [blame] | 47 | } |
| 48 | |
Russ Cox | b15c424 | 2010-12-07 16:15:15 -0500 | [diff] [blame] | 49 | // Accept waits for and returns the next incoming TLS connection. |
Brad Fitzpatrick | 351c15f | 2016-02-28 15:52:49 -0800 | [diff] [blame] | 50 | // The returned connection is of type *Conn. |
| 51 | func (l *listener) Accept() (net.Conn, error) { |
| 52 | c, err := l.Listener.Accept() |
Adam Langley | 950f263 | 2009-11-05 16:43:29 -0800 | [diff] [blame] | 53 | if err != nil { |
Brad Fitzpatrick | 351c15f | 2016-02-28 15:52:49 -0800 | [diff] [blame] | 54 | return nil, err |
Adam Langley | 950f263 | 2009-11-05 16:43:29 -0800 | [diff] [blame] | 55 | } |
Brad Fitzpatrick | 351c15f | 2016-02-28 15:52:49 -0800 | [diff] [blame] | 56 | return Server(c, l.config), nil |
Adam Langley | 950f263 | 2009-11-05 16:43:29 -0800 | [diff] [blame] | 57 | } |
| 58 | |
Adam Langley | 950f263 | 2009-11-05 16:43:29 -0800 | [diff] [blame] | 59 | // NewListener creates a Listener which accepts connections from an inner |
| 60 | // Listener and wraps each connection with Server. |
aubble | 34695c4 | 2015-08-20 14:26:56 -0400 | [diff] [blame] | 61 | // The configuration config must be non-nil and must include |
| 62 | // at least one certificate or else set GetCertificate. |
Adam Langley | 005686f | 2012-02-03 15:08:53 -0500 | [diff] [blame] | 63 | func NewListener(inner net.Listener, config *Config) net.Listener { |
| 64 | l := new(listener) |
| 65 | l.Listener = inner |
Robert Griesemer | 5a1d332 | 2009-12-15 15:33:31 -0800 | [diff] [blame] | 66 | l.config = config |
Adam Langley | 005686f | 2012-02-03 15:08:53 -0500 | [diff] [blame] | 67 | return l |
Adam Langley | 950f263 | 2009-11-05 16:43:29 -0800 | [diff] [blame] | 68 | } |
Russ Cox | 99d258a | 2010-04-05 14:38:02 -0700 | [diff] [blame] | 69 | |
Russ Cox | b15c424 | 2010-12-07 16:15:15 -0500 | [diff] [blame] | 70 | // Listen creates a TLS listener accepting connections on the |
| 71 | // given network address using net.Listen. |
aubble | 34695c4 | 2015-08-20 14:26:56 -0400 | [diff] [blame] | 72 | // The configuration config must be non-nil and must include |
| 73 | // at least one certificate or else set GetCertificate. |
Adam Langley | 005686f | 2012-02-03 15:08:53 -0500 | [diff] [blame] | 74 | func Listen(network, laddr string, config *Config) (net.Listener, error) { |
aubble | bfa0161 | 2015-08-20 14:31:15 -0400 | [diff] [blame] | 75 | if config == nil || (len(config.Certificates) == 0 && config.GetCertificate == nil) { |
| 76 | return nil, errors.New("tls: neither Certificates nor GetCertificate set in Config") |
Russ Cox | 72d9322 | 2010-04-26 22:19:04 -0700 | [diff] [blame] | 77 | } |
Russ Cox | 99d258a | 2010-04-05 14:38:02 -0700 | [diff] [blame] | 78 | l, err := net.Listen(network, laddr) |
| 79 | if err != nil { |
| 80 | return nil, err |
| 81 | } |
Russ Cox | 72d9322 | 2010-04-26 22:19:04 -0700 | [diff] [blame] | 82 | return NewListener(l, config), nil |
Russ Cox | 99d258a | 2010-04-05 14:38:02 -0700 | [diff] [blame] | 83 | } |
| 84 | |
Adam Langley | 1f8b2a6 | 2014-02-28 09:40:12 -0500 | [diff] [blame] | 85 | type timeoutError struct{} |
| 86 | |
| 87 | func (timeoutError) Error() string { return "tls: DialWithDialer timed out" } |
| 88 | func (timeoutError) Timeout() bool { return true } |
| 89 | func (timeoutError) Temporary() bool { return true } |
| 90 | |
| 91 | // DialWithDialer connects to the given network address using dialer.Dial and |
| 92 | // then initiates a TLS handshake, returning the resulting TLS connection. Any |
| 93 | // timeout or deadline given in the dialer apply to connection and TLS |
| 94 | // handshake as a whole. |
| 95 | // |
| 96 | // DialWithDialer interprets a nil configuration as equivalent to the zero |
| 97 | // configuration; see the documentation of Config for the defaults. |
| 98 | func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { |
| 99 | // We want the Timeout and Deadline values from dialer to cover the |
| 100 | // whole process: TCP connection and TLS handshake. This means that we |
| 101 | // also need to start our own timers now. |
| 102 | timeout := dialer.Timeout |
| 103 | |
| 104 | if !dialer.Deadline.IsZero() { |
| 105 | deadlineTimeout := dialer.Deadline.Sub(time.Now()) |
| 106 | if timeout == 0 || deadlineTimeout < timeout { |
| 107 | timeout = deadlineTimeout |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | var errChannel chan error |
| 112 | |
| 113 | if timeout != 0 { |
| 114 | errChannel = make(chan error, 2) |
| 115 | time.AfterFunc(timeout, func() { |
| 116 | errChannel <- timeoutError{} |
| 117 | }) |
| 118 | } |
| 119 | |
| 120 | rawConn, err := dialer.Dial(network, addr) |
Russ Cox | 99d258a | 2010-04-05 14:38:02 -0700 | [diff] [blame] | 121 | if err != nil { |
| 122 | return nil, err |
| 123 | } |
Adam Langley | 836529a | 2010-11-05 09:54:56 -0400 | [diff] [blame] | 124 | |
Adam Langley | 1f8b2a6 | 2014-02-28 09:40:12 -0500 | [diff] [blame] | 125 | colonPos := strings.LastIndex(addr, ":") |
Adam Langley | 836529a | 2010-11-05 09:54:56 -0400 | [diff] [blame] | 126 | if colonPos == -1 { |
Adam Langley | 1f8b2a6 | 2014-02-28 09:40:12 -0500 | [diff] [blame] | 127 | colonPos = len(addr) |
Adam Langley | 836529a | 2010-11-05 09:54:56 -0400 | [diff] [blame] | 128 | } |
Adam Langley | 1f8b2a6 | 2014-02-28 09:40:12 -0500 | [diff] [blame] | 129 | hostname := addr[:colonPos] |
Adam Langley | 836529a | 2010-11-05 09:54:56 -0400 | [diff] [blame] | 130 | |
Russ Cox | b15c424 | 2010-12-07 16:15:15 -0500 | [diff] [blame] | 131 | if config == nil { |
| 132 | config = defaultConfig() |
Adam Langley | 6989f6e | 2010-09-20 10:32:08 -0400 | [diff] [blame] | 133 | } |
Mikkel Krautz | a324a5a | 2012-03-07 13:12:35 -0500 | [diff] [blame] | 134 | // If no ServerName is set, infer the ServerName |
| 135 | // from the hostname we're connecting to. |
| 136 | if config.ServerName == "" { |
Russ Cox | b15c424 | 2010-12-07 16:15:15 -0500 | [diff] [blame] | 137 | // Make a copy to avoid polluting argument or default. |
| 138 | c := *config |
| 139 | c.ServerName = hostname |
| 140 | config = &c |
| 141 | } |
Adam Langley | 1f8b2a6 | 2014-02-28 09:40:12 -0500 | [diff] [blame] | 142 | |
| 143 | conn := Client(rawConn, config) |
| 144 | |
| 145 | if timeout == 0 { |
| 146 | err = conn.Handshake() |
| 147 | } else { |
| 148 | go func() { |
| 149 | errChannel <- conn.Handshake() |
| 150 | }() |
| 151 | |
| 152 | err = <-errChannel |
| 153 | } |
| 154 | |
| 155 | if err != nil { |
| 156 | rawConn.Close() |
Russ Cox | b15c424 | 2010-12-07 16:15:15 -0500 | [diff] [blame] | 157 | return nil, err |
| 158 | } |
Adam Langley | 1f8b2a6 | 2014-02-28 09:40:12 -0500 | [diff] [blame] | 159 | |
Russ Cox | b15c424 | 2010-12-07 16:15:15 -0500 | [diff] [blame] | 160 | return conn, nil |
Russ Cox | 99d258a | 2010-04-05 14:38:02 -0700 | [diff] [blame] | 161 | } |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 162 | |
Adam Langley | 1f8b2a6 | 2014-02-28 09:40:12 -0500 | [diff] [blame] | 163 | // Dial connects to the given network address using net.Dial |
| 164 | // and then initiates a TLS handshake, returning the resulting |
| 165 | // TLS connection. |
| 166 | // Dial interprets a nil configuration as equivalent to |
| 167 | // the zero configuration; see the documentation of Config |
| 168 | // for the defaults. |
| 169 | func Dial(network, addr string, config *Config) (*Conn, error) { |
| 170 | return DialWithDialer(new(net.Dialer), network, addr, config) |
| 171 | } |
| 172 | |
Adam Langley | f6e2eab | 2010-10-11 10:39:56 -0400 | [diff] [blame] | 173 | // LoadX509KeyPair reads and parses a public/private key pair from a pair of |
Adam Langley | b203f88 | 2016-01-19 08:27:10 -0800 | [diff] [blame] | 174 | // files. The files must contain PEM encoded data. On successful return, |
| 175 | // Certificate.Leaf will be nil because the parsed form of the certificate is |
| 176 | // not retained. |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 177 | func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) { |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 178 | certPEMBlock, err := ioutil.ReadFile(certFile) |
| 179 | if err != nil { |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 180 | return Certificate{}, err |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 181 | } |
Brad Fitzpatrick | cc40870 | 2011-04-04 08:32:59 -0700 | [diff] [blame] | 182 | keyPEMBlock, err := ioutil.ReadFile(keyFile) |
| 183 | if err != nil { |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 184 | return Certificate{}, err |
Brad Fitzpatrick | cc40870 | 2011-04-04 08:32:59 -0700 | [diff] [blame] | 185 | } |
| 186 | return X509KeyPair(certPEMBlock, keyPEMBlock) |
| 187 | } |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 188 | |
Brad Fitzpatrick | cc40870 | 2011-04-04 08:32:59 -0700 | [diff] [blame] | 189 | // X509KeyPair parses a public/private key pair from a pair of |
Adam Langley | b203f88 | 2016-01-19 08:27:10 -0800 | [diff] [blame] | 190 | // PEM encoded data. On successful return, Certificate.Leaf will be nil because |
| 191 | // the parsed form of the certificate is not retained. |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 192 | func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 193 | fail := func(err error) (Certificate, error) { return Certificate{}, err } |
Adam Langley | be16001 | 2015-08-30 10:23:30 -0700 | [diff] [blame] | 194 | |
| 195 | var cert Certificate |
| 196 | var skippedBlockTypes []string |
Adam Langley | 5626bd9 | 2011-02-05 13:54:25 -0500 | [diff] [blame] | 197 | for { |
Adam Langley | be16001 | 2015-08-30 10:23:30 -0700 | [diff] [blame] | 198 | var certDERBlock *pem.Block |
Adam Langley | 5626bd9 | 2011-02-05 13:54:25 -0500 | [diff] [blame] | 199 | certDERBlock, certPEMBlock = pem.Decode(certPEMBlock) |
| 200 | if certDERBlock == nil { |
| 201 | break |
| 202 | } |
| 203 | if certDERBlock.Type == "CERTIFICATE" { |
| 204 | cert.Certificate = append(cert.Certificate, certDERBlock.Bytes) |
Adam Langley | be16001 | 2015-08-30 10:23:30 -0700 | [diff] [blame] | 205 | } else { |
| 206 | skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type) |
Adam Langley | 5626bd9 | 2011-02-05 13:54:25 -0500 | [diff] [blame] | 207 | } |
| 208 | } |
| 209 | |
| 210 | if len(cert.Certificate) == 0 { |
Adam Langley | be16001 | 2015-08-30 10:23:30 -0700 | [diff] [blame] | 211 | if len(skippedBlockTypes) == 0 { |
| 212 | return fail(errors.New("crypto/tls: failed to find any PEM data in certificate input")) |
Adam Langley | be16001 | 2015-08-30 10:23:30 -0700 | [diff] [blame] | 213 | } |
Emmanuel Odeke | f0711b9 | 2016-03-14 03:35:13 -0600 | [diff] [blame^] | 214 | if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") { |
| 215 | 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")) |
| 216 | } |
| 217 | 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)) |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 218 | } |
| 219 | |
Adam Langley | be16001 | 2015-08-30 10:23:30 -0700 | [diff] [blame] | 220 | skippedBlockTypes = skippedBlockTypes[:0] |
Adam Langley | ecc04b8 | 2012-09-13 11:00:16 -0400 | [diff] [blame] | 221 | var keyDERBlock *pem.Block |
| 222 | for { |
| 223 | keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock) |
| 224 | if keyDERBlock == nil { |
Adam Langley | be16001 | 2015-08-30 10:23:30 -0700 | [diff] [blame] | 225 | if len(skippedBlockTypes) == 0 { |
| 226 | return fail(errors.New("crypto/tls: failed to find any PEM data in key input")) |
Adam Langley | be16001 | 2015-08-30 10:23:30 -0700 | [diff] [blame] | 227 | } |
Emmanuel Odeke | f0711b9 | 2016-03-14 03:35:13 -0600 | [diff] [blame^] | 228 | if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" { |
| 229 | return fail(errors.New("crypto/tls: found a certificate rather than a key in the PEM for the private key")) |
| 230 | } |
| 231 | 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)) |
Adam Langley | ecc04b8 | 2012-09-13 11:00:16 -0400 | [diff] [blame] | 232 | } |
Brad Fitzpatrick | 444b7b5 | 2012-12-01 11:02:08 -0800 | [diff] [blame] | 233 | if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") { |
Adam Langley | ecc04b8 | 2012-09-13 11:00:16 -0400 | [diff] [blame] | 234 | break |
| 235 | } |
Adam Langley | be16001 | 2015-08-30 10:23:30 -0700 | [diff] [blame] | 236 | skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type) |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 237 | } |
| 238 | |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 239 | var err error |
Joel Sing | aaf3b71 | 2012-11-16 19:33:59 +1100 | [diff] [blame] | 240 | cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes) |
| 241 | if err != nil { |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 242 | return fail(err) |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 243 | } |
| 244 | |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 245 | // We don't need to parse the public key for TLS, but we so do anyway |
| 246 | // to check that it looks sane and matches the private key. |
Adam Langley | 5626bd9 | 2011-02-05 13:54:25 -0500 | [diff] [blame] | 247 | x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 248 | if err != nil { |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 249 | return fail(err) |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 250 | } |
| 251 | |
Joel Sing | aaf3b71 | 2012-11-16 19:33:59 +1100 | [diff] [blame] | 252 | switch pub := x509Cert.PublicKey.(type) { |
| 253 | case *rsa.PublicKey: |
| 254 | priv, ok := cert.PrivateKey.(*rsa.PrivateKey) |
| 255 | if !ok { |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 256 | return fail(errors.New("crypto/tls: private key type does not match public key type")) |
Joel Sing | aaf3b71 | 2012-11-16 19:33:59 +1100 | [diff] [blame] | 257 | } |
| 258 | if pub.N.Cmp(priv.N) != 0 { |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 259 | return fail(errors.New("crypto/tls: private key does not match public key")) |
Joel Sing | aaf3b71 | 2012-11-16 19:33:59 +1100 | [diff] [blame] | 260 | } |
| 261 | case *ecdsa.PublicKey: |
| 262 | priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey) |
| 263 | if !ok { |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 264 | return fail(errors.New("crypto/tls: private key type does not match public key type")) |
Joel Sing | aaf3b71 | 2012-11-16 19:33:59 +1100 | [diff] [blame] | 265 | } |
| 266 | if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 267 | return fail(errors.New("crypto/tls: private key does not match public key")) |
Joel Sing | aaf3b71 | 2012-11-16 19:33:59 +1100 | [diff] [blame] | 268 | } |
| 269 | default: |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 270 | return fail(errors.New("crypto/tls: unknown public key algorithm")) |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 271 | } |
| 272 | |
Brad Fitzpatrick | 552080c | 2015-01-13 11:34:46 -0800 | [diff] [blame] | 273 | return cert, nil |
Adam Langley | fc23def | 2010-07-02 13:00:18 -0400 | [diff] [blame] | 274 | } |
Joel Sing | aaf3b71 | 2012-11-16 19:33:59 +1100 | [diff] [blame] | 275 | |
| 276 | // Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates |
| 277 | // PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys. |
| 278 | // OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. |
| 279 | func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { |
| 280 | if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { |
| 281 | return key, nil |
| 282 | } |
| 283 | if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { |
| 284 | switch key := key.(type) { |
| 285 | case *rsa.PrivateKey, *ecdsa.PrivateKey: |
| 286 | return key, nil |
| 287 | default: |
| 288 | return nil, errors.New("crypto/tls: found unknown private key type in PKCS#8 wrapping") |
| 289 | } |
| 290 | } |
| 291 | if key, err := x509.ParseECPrivateKey(der); err == nil { |
| 292 | return key, nil |
| 293 | } |
| 294 | |
| 295 | return nil, errors.New("crypto/tls: failed to parse private key") |
| 296 | } |