// 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" "crypto/rand" "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 typeNewSessionTicket uint8 = 4 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 extensionSessionTicket uint16 = 35 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 DidResume 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 } // ClientAuthType declares the policy the server will follow for // TLS Client Authentication. type ClientAuthType int const ( NoClientCert ClientAuthType = iota RequestClientCert RequireAnyClientCert VerifyClientCertIfGiven RequireAndVerifyClientCert ) // 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 time.Now. Time func() time.Time // 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 // ClientAuth determines the server's policy for // TLS Client Authentication. The default is NoClientCert. ClientAuth ClientAuthType // ClientCAs defines the set of root certificate authorities // that servers use if required to verify a client certificate // by the policy in ClientAuth. ClientCAs *x509.CertPool // 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 // PreferServerCipherSuites controls whether the server selects the // client's most preferred ciphersuite, or the server's most preferred // ciphersuite. If true then the server's preference, as expressed in // the order of elements in CipherSuites, is used. PreferServerCipherSuites bool // SessionTicketsDisabled may be set to true to disable session ticket // (resumption) support. SessionTicketsDisabled bool // SessionTicketKey is used by TLS servers to provide session // resumption. See RFC 5077. If zero, it will be filled with // random data before the first server handshake. // // If multiple servers are terminating connections for the same host // they should all have the same SessionTicketKey. If the // SessionTicketKey leaks, previously recorded and future TLS // connections using that key are compromised. SessionTicketKey [32]byte serverInitOnce sync.Once // guards calling (*Config).serverInit } func (c *Config) serverInit() { if c.SessionTicketsDisabled { return } // If the key has already been set then we have nothing to do. for _, b := range c.SessionTicketKey { if b != 0 { return } } if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil { c.SessionTicketsDisabled = true } } func (c *Config) rand() io.Reader { r := c.Rand if r == nil { return rand.Reader } return r } func (c *Config) time() time.Time { t := c.Time if t == nil { t = time.Now } return t() } 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 crypto.PrivateKey // supported types: *rsa.PrivateKey // OCSPStaple contains an optional OCSP response which will be served // to clients that request it. OCSPStaple []byte // Leaf is the parsed form of the leaf certificate, which may be // initialized using x509.ParseCertificate to reduce per-handshake // processing for TLS clients doing client authentication. If nil, the // leaf certificate will be parsed as needed. Leaf *x509.Certificate } // 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 varDefaultCipherSuites []uint16 ) func defaultCipherSuites() []uint16 { once.Do(initDefaultCipherSuites) return varDefaultCipherSuites } func initDefaultCipherSuites() { varDefaultCipherSuites = make([]uint16, len(cipherSuites)) for i, suite := range cipherSuites { varDefaultCipherSuites[i] = suite.id } }