| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package tls | |
| import ( | |
| "crypto/rand" | |
| "crypto/rsa" | |
| "crypto/x509" | |
| "io" | |
| "strings" | |
| "sync" | |
| "time" | |
| ) | |
| const ( | |
| maxPlaintext = 16384 // maximum plaintext payload length | |
| maxCiphertext = 16384 + 2048 // maximum ciphertext payload length | |
| recordHeaderLen = 5 // record header length | |
| maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) | |
| versionSSL30 = 0x0300 | |
| versionTLS10 = 0x0301 | |
| minVersion = versionSSL30 | |
| maxVersion = versionTLS10 | |
| ) | |
| // TLS record types. | |
| type recordType uint8 | |
| const ( | |
| recordTypeChangeCipherSpec recordType = 20 | |
| recordTypeAlert recordType = 21 | |
| recordTypeHandshake recordType = 22 | |
| recordTypeApplicationData recordType = 23 | |
| ) | |
| // TLS handshake message types. | |
| const ( | |
| typeClientHello uint8 = 1 | |
| typeServerHello uint8 = 2 | |
| typeCertificate uint8 = 11 | |
| typeServerKeyExchange uint8 = 12 | |
| typeCertificateRequest uint8 = 13 | |
| typeServerHelloDone uint8 = 14 | |
| typeCertificateVerify uint8 = 15 | |
| typeClientKeyExchange uint8 = 16 | |
| typeFinished uint8 = 20 | |
| typeCertificateStatus uint8 = 22 | |
| typeNextProtocol uint8 = 67 // Not IANA assigned | |
| ) | |
| // TLS compression types. | |
| const ( | |
| compressionNone uint8 = 0 | |
| ) | |
| // TLS extension numbers | |
| var ( | |
| extensionServerName uint16 = 0 | |
| extensionStatusRequest uint16 = 5 | |
| extensionSupportedCurves uint16 = 10 | |
| extensionSupportedPoints uint16 = 11 | |
| extensionNextProtoNeg uint16 = 13172 // not IANA assigned | |
| ) | |
| // TLS Elliptic Curves | |
| // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 | |
| var ( | |
| curveP256 uint16 = 23 | |
| curveP384 uint16 = 24 | |
| curveP521 uint16 = 25 | |
| ) | |
| // TLS Elliptic Curve Point Formats | |
| // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 | |
| var ( | |
| pointFormatUncompressed uint8 = 0 | |
| ) | |
| // TLS CertificateStatusType (RFC 3546) | |
| const ( | |
| statusTypeOCSP uint8 = 1 | |
| ) | |
| // Certificate types (for certificateRequestMsg) | |
| const ( | |
| certTypeRSASign = 1 // A certificate containing an RSA key | |
| certTypeDSSSign = 2 // A certificate containing a DSA key | |
| certTypeRSAFixedDH = 3 // A certificate containing a static DH key | |
| certTypeDSSFixedDH = 4 // A certificate containing a static DH key | |
| // Rest of these are reserved by the TLS spec | |
| ) | |
| // ConnectionState records basic TLS details about the connection. | |
| type ConnectionState struct { | |
| HandshakeComplete bool | |
| CipherSuite uint16 | |
| NegotiatedProtocol string | |
| NegotiatedProtocolIsMutual bool | |
| // ServerName contains the server name indicated by the client, if any. | |
| // (Only valid for server connections.) | |
| ServerName string | |
| // the certificate chain that was presented by the other side | |
| PeerCertificates []*x509.Certificate | |
| // the verified certificate chains built from PeerCertificates. | |
| VerifiedChains [][]*x509.Certificate | |
| } | |
| // A Config structure is used to configure a TLS client or server. After one | |
| // has been passed to a TLS function it must not be modified. | |
| type Config struct { | |
| // Rand provides the source of entropy for nonces and RSA blinding. | |
| // If Rand is nil, TLS uses the cryptographic random reader in package | |
| // crypto/rand. | |
| Rand io.Reader | |
| // Time returns the current time as the number of seconds since the epoch. | |
| // If Time is nil, TLS uses the system time.Seconds. | |
| Time func() int64 | |
| // Certificates contains one or more certificate chains | |
| // to present to the other side of the connection. | |
| // Server configurations must include at least one certificate. | |
| Certificates []Certificate | |
| // NameToCertificate maps from a certificate name to an element of | |
| // Certificates. Note that a certificate name can be of the form | |
| // '*.example.com' and so doesn't have to be a domain name as such. | |
| // See Config.BuildNameToCertificate | |
| // The nil value causes the first element of Certificates to be used | |
| // for all connections. | |
| NameToCertificate map[string]*Certificate | |
| // RootCAs defines the set of root certificate authorities | |
| // that clients use when verifying server certificates. | |
| // If RootCAs is nil, TLS uses the host's root CA set. | |
| RootCAs *x509.CertPool | |
| // NextProtos is a list of supported, application level protocols. | |
| NextProtos []string | |
| // ServerName is included in the client's handshake to support virtual | |
| // hosting. | |
| ServerName string | |
| // AuthenticateClient controls whether a server will request a certificate | |
| // from the client. It does not require that the client send a | |
| // certificate nor does it require that the certificate sent be | |
| // anything more than self-signed. | |
| AuthenticateClient bool | |
| // InsecureSkipVerify controls whether a client verifies the | |
| // server's certificate chain and host name. | |
| // If InsecureSkipVerify is true, TLS accepts any certificate | |
| // presented by the server and any host name in that certificate. | |
| // In this mode, TLS is susceptible to man-in-the-middle attacks. | |
| // This should be used only for testing. | |
| InsecureSkipVerify bool | |
| // CipherSuites is a list of supported cipher suites. If CipherSuites | |
| // is nil, TLS uses a list of suites supported by the implementation. | |
| CipherSuites []uint16 | |
| } | |
| func (c *Config) rand() io.Reader { | |
| r := c.Rand | |
| if r == nil { | |
| return rand.Reader | |
| } | |
| return r | |
| } | |
| func (c *Config) time() int64 { | |
| t := c.Time | |
| if t == nil { | |
| t = time.Seconds | |
| } | |
| return t() | |
| } | |
| func (c *Config) rootCAs() *x509.CertPool { | |
| s := c.RootCAs | |
| if s == nil { | |
| s = defaultRoots() | |
| } | |
| return s | |
| } | |
| func (c *Config) cipherSuites() []uint16 { | |
| s := c.CipherSuites | |
| if s == nil { | |
| s = defaultCipherSuites() | |
| } | |
| return s | |
| } | |
| // getCertificateForName returns the best certificate for the given name, | |
| // defaulting to the first element of c.Certificates if there are no good | |
| // options. | |
| func (c *Config) getCertificateForName(name string) *Certificate { | |
| if len(c.Certificates) == 1 || c.NameToCertificate == nil { | |
| // There's only one choice, so no point doing any work. | |
| return &c.Certificates[0] | |
| } | |
| name = strings.ToLower(name) | |
| for len(name) > 0 && name[len(name)-1] == '.' { | |
| name = name[:len(name)-1] | |
| } | |
| if cert, ok := c.NameToCertificate[name]; ok { | |
| return cert | |
| } | |
| // try replacing labels in the name with wildcards until we get a | |
| // match. | |
| labels := strings.Split(name, ".") | |
| for i := range labels { | |
| labels[i] = "*" | |
| candidate := strings.Join(labels, ".") | |
| if cert, ok := c.NameToCertificate[candidate]; ok { | |
| return cert | |
| } | |
| } | |
| // If nothing matches, return the first certificate. | |
| return &c.Certificates[0] | |
| } | |
| // BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate | |
| // from the CommonName and SubjectAlternateName fields of each of the leaf | |
| // certificates. | |
| func (c *Config) BuildNameToCertificate() { | |
| c.NameToCertificate = make(map[string]*Certificate) | |
| for i := range c.Certificates { | |
| cert := &c.Certificates[i] | |
| x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) | |
| if err != nil { | |
| continue | |
| } | |
| if len(x509Cert.Subject.CommonName) > 0 { | |
| c.NameToCertificate[x509Cert.Subject.CommonName] = cert | |
| } | |
| for _, san := range x509Cert.DNSNames { | |
| c.NameToCertificate[san] = cert | |
| } | |
| } | |
| } | |
| // A Certificate is a chain of one or more certificates, leaf first. | |
| type Certificate struct { | |
| Certificate [][]byte | |
| PrivateKey *rsa.PrivateKey | |
| // OCSPStaple contains an optional OCSP response which will be served | |
| // to clients that request it. | |
| OCSPStaple []byte | |
| } | |
| // A TLS record. | |
| type record struct { | |
| contentType recordType | |
| major, minor uint8 | |
| payload []byte | |
| } | |
| type handshakeMessage interface { | |
| marshal() []byte | |
| unmarshal([]byte) bool | |
| } | |
| // mutualVersion returns the protocol version to use given the advertised | |
| // version of the peer. | |
| func mutualVersion(vers uint16) (uint16, bool) { | |
| if vers < minVersion { | |
| return 0, false | |
| } | |
| if vers > maxVersion { | |
| vers = maxVersion | |
| } | |
| return vers, true | |
| } | |
| var emptyConfig Config | |
| func defaultConfig() *Config { | |
| return &emptyConfig | |
| } | |
| var once sync.Once | |
| func defaultRoots() *x509.CertPool { | |
| once.Do(initDefaults) | |
| return varDefaultRoots | |
| } | |
| func defaultCipherSuites() []uint16 { | |
| once.Do(initDefaults) | |
| return varDefaultCipherSuites | |
| } | |
| func initDefaults() { | |
| initDefaultRoots() | |
| initDefaultCipherSuites() | |
| } | |
| var ( | |
| varDefaultRoots *x509.CertPool | |
| varDefaultCipherSuites []uint16 | |
| ) | |
| func initDefaultCipherSuites() { | |
| varDefaultCipherSuites = make([]uint16, len(cipherSuites)) | |
| i := 0 | |
| for id := range cipherSuites { | |
| varDefaultCipherSuites[i] = id | |
| i++ | |
| } | |
| } |